[英]How can I make a copy of an iterator in Java?
我們有一個元素列表,並且有一個非常簡單的碰撞檢測,我們檢查每個對象與其他所有對象。
檢查是可交換的,所以為避免重復兩次,我們將在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寫這個?
您無法復制Java迭代器,因此您必須在沒有它們的情況下執行此操作:
for(int i=0; i<list.size(); i++){
for(int j=i; j<list.size(); j++){
Test(list.get(i), list.get(j));
}
}
您可以使用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³)。 (如果先將列表復制到數組中,可能會更快,但這只是一個常數因素。)
當然,如果您通常需要基於索引的訪問(或此迭代器克隆),則最好使用基於數組的列表(或迭代器支持克隆的自定義列表)。
對於一個鏈表(索引訪問速度慢),我認為有一種方法可以做到這一點,而不會引起Paŭlo提到的O(n²)減速。 只要您不關心訪問列表的順序,就可以從最后一個元素開始外循環並迭代回來,從第一個元素開始內循環並向前迭代直到兩個迭代器相遇。 請參閱下面的代碼中的iterRevIterator
。 對list.listIterator(list.size())
的調用很快,因為list
是LinkedList
,即雙向鏈表,並且訪問最后一個元素不需要遍歷列表。 差異不是很大......
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);
}
}
for(int i = 0; i < list.size(); i++) {
for(int j = i; j < list.size(); j++){
Test(list.get(i), list.get(j));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.