如何在Java中复制迭代器?

时间:2011-05-11 11:23:58

标签: java iterator copy

我们有一个元素列表,并且有一个非常简单的碰撞检测,我们检查每个对象与其他所有对象。

检查是可交换的,所以为避免重复两次,我们将在C ++中执行此操作:

for (list<Object>::iterator it0 = list.begin(); it0 != list.end(); ++it0)
{
    for (list<Object>::iterator it1 = it0; it1 != list.end(); ++it1)
    {
        Test(*it0, *it1);
    }
}

这里的关键位是副本

it1 = it0

你会怎么用Java写这个?

4 个答案:

答案 0 :(得分:7)

您无法复制Java迭代器,因此您必须在没有它们的情况下执行此操作:

for(int i=0; i<list.size(); i++){
    for(int j=i; j<list.size(); j++){
        Test(list.get(i), list.get(j));
    }
}

答案 1 :(得分:6)

您可以使用ListIterator执行此操作:

for(ListIterator<O> outer = list.listIterator(); outer.hasNext() ; ) {
    O oVal = outer.next();
    for(ListIterator<O> inner = list.listIterator(outer.nextIndex()); inner.hasNext(); ) {
         Test(oVal, inner.next());
    }
}

对于链接列表(索引访问速度较慢),list.listIterator(index)仍然需要迭代到正确的位置。 但是这样只有O(n²)(并且你不能比这更好)而不是像其他答案中的索引访问那样的O(n³)。 (如果先将列表复制到数组中,可能会更快,但这只是一个常数因素。)

当然,如果您通常需要基于索引的访问(或此迭代器克隆),您最好使用基于数组的列表(或迭代器支持克隆的自定义列表)。

答案 2 :(得分:4)

对于一个链表(索引访问速度慢),我认为有一种方法可以做到这一点,而不会引起Paŭlo提到的O(n²)减速。只要您不关心访问列表的顺序,就可以从最后一个元素开始外循环并迭代回来,从第一个元素开始内循环并向前迭代直到两个迭代器相遇。请参阅以下代码中的iterRevIterator。对list.listIterator(list.size())的调用很快,因为listLinkedList,即双向链表,并且访问最后一个元素不需要遍历列表。 差异并不大......

iterIndex: 384.59ms sum=29656666
iterIterator: 1.91ms sum=29656666
iterRevIterator: 1.55ms sum=29656666

但仍然很重要。

import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.ListIterator;


public class TestIter {

    public static int iterIndex(List<Integer> list) {
        int sum = 0;
        for(int i = 0; i < list.size(); ++i) {
            for(int j = i+1; j < list.size(); ++j) {
                sum += list.get(i) * list.get(j);
            }
        }
        return sum;
    }

    public static int iterIterator(List<Integer> list) {
        int sum = 0;
        for(ListIterator<Integer> outer = list.listIterator(); outer.hasNext() ; ) {
            Integer oVal = outer.next();
            for(ListIterator<Integer> inner = list.listIterator(outer.nextIndex()); inner.hasNext(); ) {
                sum += oVal * inner.next();
            }
        }
        return sum;
    }

    public static int iterRevIterator(List<Integer> list) {
        int sum = 0;
        for(ListIterator<Integer> outer = list.listIterator(list.size()); outer.hasPrevious() ; ) {
            Integer oVal = outer.previous();
            for(ListIterator<Integer> inner = list.listIterator(); inner.nextIndex() <= outer.previousIndex(); ) {
                sum += oVal * inner.next();
            }
        }
        return sum;
    }

    public static void main(String[] args) {
        int size = 1000;
        int rep = 100;
        int sum = 0;
        // List<Integer> list = new ArrayList<Integer>();
        List<Integer> list = new LinkedList<Integer>();
        for (int i = 0; i < size; ++i) {
            list.add(i);
        }

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < rep; ++i) {
            sum = iterIndex(list);
        }
        System.out.println("iterIndex: " + (float)(System.currentTimeMillis() - startTime)/rep + "ms sum=" + sum);

        startTime = System.currentTimeMillis();
        for (int i = 0; i < rep; ++i) {
            sum = iterIterator(list);
        }
        System.out.println("iterIterator: " + (float)(System.currentTimeMillis() - startTime)/rep + "ms sum=" + sum);

        startTime = System.currentTimeMillis();
        for (int i = 0; i < rep; ++i) {
            sum = iterRevIterator(list);
        }
        System.out.println("iterRevIterator: " + (float)(System.currentTimeMillis() - startTime)/rep + "ms sum=" + sum);

    }

}

答案 3 :(得分:1)

for(int i = 0; i < list.size(); i++) {
  for(int j = i; j < list.size(); j++){
    Test(list.get(i), list.get(j));
  }
}