如何在Java中复制迭代器?

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

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

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

这里的关键是副本

 it1 = it0 

你会怎么用Java写这个?

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

 for(int i=0; i 

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

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

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

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

对于一个链表(索引访问速度慢),我认为有一种方法可以做到这一点,而不会引起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 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 list) { int sum = 0; for(ListIterator outer = list.listIterator(); outer.hasNext() ; ) { Integer oVal = outer.next(); for(ListIterator inner = list.listIterator(outer.nextIndex()); inner.hasNext(); ) { sum += oVal * inner.next(); } } return sum; } public static int iterRevIterator(List list) { int sum = 0; for(ListIterator outer = list.listIterator(list.size()); outer.hasPrevious() ; ) { Integer oVal = outer.previous(); for(ListIterator 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 list = new ArrayList(); List list = new LinkedList(); 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); } } 
 for(int i = 0; i < list.size(); i++) { for(int j = i; j < list.size(); j++){ Test(list.get(i), list.get(j)); } }