You can also use IteratorUtils
from Apache commons-collections, although it doesn't support generics:
List list = IteratorUtils.toList(iterator);
Pretty concise solution with plain Java 8 using java.util.stream
:
public static <T> ArrayList<T> toArrayList(final Iterator<T> iterator) {
return StreamSupport
.stream(
Spliterators
.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
.collect(
Collectors.toCollection(ArrayList::new)
);
}
Note there is a difference between Iterable
and Iterator
.
If you have an Iterable
, then with Java 8 you can use this solution:
Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
As I know Collectors.toList()
creates ArrayList
instance.
Actually in my opinion, it also looks good in one line.
For example if you need to return List<Element>
from some method:
return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
Here's a one-liner using Streams
Iterator<?> iterator = ...
List<?> list = StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false)
.collect(Collectors.toList());
I just want to point out a seemingly obvious solution that will NOT work:
List list = Stream.generate(iterator::next) .collect(Collectors.toList());
That's because Stream#generate(Supplier<T>)
can create only infinite streams, it doesn't expect its argument to throw NoSuchElementException
(that's what Iterator#next()
will do in the end).
The xehpuk's answer should be used instead if the Iterator?Stream?List way is your choice.
Here in this case if you want the fastest way possible then for loop
is better.
The iterator over a sample size of 10,000 runs
takes 40 ms
where as for loop takes 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));
That's assuming that the list contains strings.
Try StickyList
from Cactoos:
List<String> list = new StickyList<>(iterable);
Disclaimer: I'm one of the developers.
In Java 8, you can use the new forEachRemaining
method that's been added to the Iterator
interface:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
You can copy an iterator to a new list like this:
Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
copy.add(iter.next());
That's assuming that the list contains strings. There really isn't a faster way to recreate a list from an iterator, you're stuck with traversing it by hand and copying each element to a new list of the appropriate type.
EDIT :
Here's a generic method for copying an iterator to a new list in a type-safe way:
public static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Use it like this:
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]
use google guava !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
Source: Stackoverflow.com