Odpowiedzi:
Lepiej użyj biblioteki takiej jak Guava :
import com.google.common.collect.Lists;
Iterator<Element> myIterator = ... //some iterator
List<Element> myList = Lists.newArrayList(myIterator);
Kolejny przykład guawy:
ImmutableList.copyOf(myIterator);
lub Kolekcje Apache Commons :
import org.apache.commons.collections.IteratorUtils;
Iterator<Element> myIterator = ...//some iterator
List<Element> myList = IteratorUtils.toList(myIterator);
W Javie 8 możesz użyć nowej forEachRemaining
metody dodanej do Iterator
interfejsu:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
::
? jakie to ma imię wydaje się bezpośrednim odniesieniem do list.add (); i wydaje się też, że jest coś nowego w java8; i dzięki! :)
::
Składnia jest nowa w Javie 8 i odnosi się do „odwołania do metody”, które jest skrótową formą lambda. Zobacz tutaj, aby uzyskać więcej informacji: docs.oracle.com/javase/tutorial/java/javaOO/…
iterator
pochodzi? jest to nierozwiązany symbol
iterator
.
Możesz skopiować iterator do nowej listy, takiej jak ta:
Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
copy.add(iter.next());
Zakłada się, że lista zawiera ciągi znaków. Naprawdę nie ma szybszego sposobu na odtworzenie listy z iteratora, utkniesz w ręcznym przechodzeniu do niej i kopiowaniu każdego elementu na nową listę odpowiedniego typu.
EDYTOWAĆ :
Oto ogólna metoda kopiowania iteratora na nową listę w sposób bezpieczny dla typu:
public static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Użyj tego w ten sposób:
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]
Uwaga: istnieje różnica między Iterable
i Iterator
.
Jeśli masz Iterable
, to w Javie 8 możesz użyć tego rozwiązania:
Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
Jak wiem Collectors.toList()
tworzy ArrayList
instancję.
Moim zdaniem w jednym wierszu wygląda dobrze.
Na przykład, jeśli chcesz wrócić List<Element>
z jakiejś metody:
return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
Iterable
iterator
. Oni są zupełnie inni.
Iterator
powrót do pojedynczego użycia Iterable
za pomocą () -> iterator
. Może to być przydatne w takich sytuacjach, ale pozwólcie, że jeszcze raz podkreślę ważną rzecz: Możesz użyć tej metody tylko wtedy, gdy jedno użycie Iterable
jest dopuszczalne. Dzwonienie iterable.iterator()
więcej niż raz da nieoczekiwane rezultaty. Powyższa odpowiedź staje sięIterator<Element> iterator = createIterator();
List<Element> array = StreamSupport.stream(((Iterable<Element>) () -> iterable).spliterator(), false).collect(toList());
Możesz także korzystać IteratorUtils
z wspólnych zbiorów Apache , chociaż nie obsługuje on ogólnych:
List list = IteratorUtils.toList(iterator);
Całkiem zwięzłe rozwiązanie z prostym Java 8 za pomocą 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)
);
}
iterator.forEachRemaining( list::add )
także nowy w Javie 8 jest o wiele bardziej zwięzły. Collector
Wepchnięcie zmiennej listy do nie poprawia czytelności w tym przypadku, ponieważ musi być obsługiwana przez a Stream
i a Spliterator
.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Spróbuj StickyList
z Cactoos :
List<String> list = new StickyList<>(iterable);
Oświadczenie: Jestem jednym z programistów.
Iterable
! =Iterator
Chcę tylko wskazać na pozornie oczywiste rozwiązanie, które NIE zadziała:
Lista list = Stream.generate (iterator :: next) .collect (Collectors.toList ());
To dlatego, że Stream#generate(Supplier<T>)
może tworzyć tylko nieskończone strumienie, nie spodziewa się, że jego argument zostanie rzucony NoSuchElementException
(to Iterator#next()
zrobi w końcu).
Zamiast tego należy użyć odpowiedzi xehpuk, jeśli Twój wybór to Iterator → Strumień → Lista.
użyj google guava !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
Tutaj w tym przypadku, jeśli chcesz najszybszy możliwy sposób, for loop
to lepiej.
Iterator na próbce wielkości 10,000 runs
ujęć, 40 ms
gdzie dla ujęć pętli2 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));
Zakłada się, że lista zawiera ciągi znaków.
for
pętli i uzyskiwanie dostępu do elementów listy get(i)
jest szybsze niż używanie iteratora ... ale nie o to prosił OP, szczególnie wspomniał, że iterator jest podawany jako dane wejściowe.
get(int)
pętli patrzysz tylko na 100 000 wpisów o długości 1 m. Jeśli zmienisz tę pętlę it.size()
, zobaczysz, że te 2 metody są zbliżone do tej samej prędkości. Ogólnie rzecz biorąc, tego rodzaju testy prędkości java dostarczają ograniczonych informacji na temat rzeczywistych wyników i należy na nie spojrzeć sceptycznie.