给定Iterator<Element>,我们如何方便地将该迭代器转换为List<Element>,以便我们可以对其使用List的操作,如get(index), add(Element)等。
当前回答
我只是想指出一个看似显而易见但行不通的解决方案:
List list = Stream.generate(iterator::next) .collect(Collectors.toList());
这是因为Stream#generate(Supplier<T>)只能创建无限的流,它并不期望它的参数抛出NoSuchElementException(这就是Iterator#next()最终会做的事情)。
如果你选择迭代器→流→列表的方式,应该使用xehpuk的答案。
其他回答
最好使用像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);
在这种情况下,如果你想要最快的方法,那么for循环会更好。
迭代器运行10,000次的样本量需要40毫秒,而for循环需要2毫秒
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));
这是假设列表中包含字符串。
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
我只是想指出一个看似显而易见但行不通的解决方案:
List list = Stream.generate(iterator::next) .collect(Collectors.toList());
这是因为Stream#generate(Supplier<T>)只能创建无限的流,它并不期望它的参数抛出NoSuchElementException(这就是Iterator#next()最终会做的事情)。
如果你选择迭代器→流→列表的方式,应该使用xehpuk的答案。
在Java 8中,你可以使用添加到Iterator接口的新的forEachRemaining方法:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);