[英]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);
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]
如果你有一個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());
我只是想指出一個看似明顯的解決方案是行不通的:
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.