簡體   English   中英

將迭代器轉換為 ArrayList

[英]Convert Iterator to ArrayList

給定Iterator<Element> ,我們如何以最好和最快的方式將該Iterator轉換為ArrayList<Element> (或List<Element> ),以便我們可以對它使用ArrayList的操作,例如get(index)add(element)

最好使用像Guava這樣的庫:

import com.google.common.collect.Lists;

Iterator<Element> myIterator = ... //some iterator
List<Element> myList = Lists.newArrayList(myIterator);

另一個番石榴示例:

ImmutableList.copyOf(myIterator);

Apache Commons Collections

import org.apache.commons.collections.IteratorUtils;

Iterator<Element> myIterator = ...//some iterator

List<Element> myList = IteratorUtils.toList(myIterator);       

在 Java 8 中,您可以使用添加到Iterator接口的新forEachRemaining方法:

List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);

您可以將迭代器復制到一個新列表,如下所示:

Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
    copy.add(iter.next());

那是假設列表包含字符串。 從迭代器重新創建列表確實沒有更快的方法,您不得不手動遍歷它並將每個元素復制到適當類型的新列表。

編輯 :

這是以類型安全的方式將迭代器復制到新列表的通用方法:

public static <T> List<T> copyIterator(Iterator<T> iter) {
    List<T> copy = new ArrayList<T>();
    while (iter.hasNext())
        copy.add(iter.next());
    return copy;
}

像這樣使用它:

List<String> list = Arrays.asList("1", "2", "3");
Iterator<String> iter = list.iterator();
List<String> copy = copyIterator(iter);
System.out.println(copy);
> [1, 2, 3]

請注意, IterableIterator之間存在差異。

如果你有一個Iterable ,那么在 Java 8 中你可以使用這個解決方案:

Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
    .stream(iterable.spliterator(), false)
    .collect(Collectors.toList());

據我所知, Collectors.toList()創建ArrayList實例。

實際上在我看來,它在一行中看起來也不錯。
例如,如果您需要從某個方法返回List<Element>

return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());

您也可以使用 Apache commons-collections 中的IteratorUtils ,盡管它不支持泛型:

List list = IteratorUtils.toList(iterator);

使用java.util.stream純 Java 8 非常簡潔的解決方案:

public static <T> ArrayList<T> toArrayList(final Iterator<T> iterator) {
    return StreamSupport
        .stream(
            Spliterators
                .spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
        .collect(
                Collectors.toCollection(ArrayList::new)
    );
}

可以在此處使用Iterator中的Java 8 forEachRemaining方法:

List<Element> elementList = new ArrayList<>(); 
iterator.forEachRemaining(elementList::add);
List result = new ArrayList();
while (i.hasNext()){
    result.add(i.next());
}

這是使用 Streams 的單行代碼

Iterator<?> iterator = ...
List<?> list = StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false)
                .collect(Collectors.toList());

嘗試StickyListCactoos

List<String> list = new StickyList<>(iterable);

免責聲明:我是開發人員之一。

我只是想指出一個看似明顯的解決方案是行不通的:

List list = Stream.generate(iterator::next)
    .collect(Collectors.toList());

這是因為Stream#generate(Supplier<T>)只能創建無限流,它不希望它的參數拋出NoSuchElementException (這就是Iterator#next()會做的)。

如果您選擇 Iterator→Stream→List 方式,則應改用 xehpuk 的答案

使用谷歌番石榴

Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);

++

在這種情況下,如果您想要最快的方式,那么for loop會更好。

超過10,000 runs的樣本大小的迭代器需要40 ms ,而 for 循環需要2 ms

        ArrayList<String> alist = new ArrayList<String>();  
        long start, end;  

        for (int i = 0; i < 1000000; i++) {  
            alist.add(String.valueOf(i));  
        }  

        ListIterator<String> it = alist.listIterator();      

        start = System.currentTimeMillis();  
        while (it.hasNext()) {  
            String s = it.next();  
        }  
        end = System.currentTimeMillis();  

        System.out.println("Iterator start: " + start + ", end: " + end + ", delta: "  
            + (end - start));  
        start = System.currentTimeMillis();  
        int ixx = 0;  
        for (int i = 0; i < 100000; i++) {  
            String s = alist.get(i);  
        }  

        System.out.println(ixx);  
        end = System.currentTimeMillis();  
        System.out.println("for loop start: " + start + ", end: " + end + ", delta: "  
            + (end - start));  

那是假設列表包含字符串。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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