簡體   English   中英

如何在Java中復制迭代器?

[英]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())的調用很快,因為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);

    }

}
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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM