Yanıtlar:
Guava gibi bir kütüphaneyi daha iyi kullanın :
import com.google.common.collect.Lists;
Iterator<Element> myIterator = ... //some iterator
List<Element> myList = Lists.newArrayList(myIterator);
Başka bir Guava örneği:
ImmutableList.copyOf(myIterator);
veya Apache Commons Koleksiyonları :
import org.apache.commons.collections.IteratorUtils;
Iterator<Element> myIterator = ...//some iterator
List<Element> myList = IteratorUtils.toList(myIterator);
Java 8'de, arabirime forEachRemaining
eklenen yeni yöntemi kullanabilirsiniz Iterator
:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
::
? hangi adı var? list.add () öğesine doğrudan bir başvuru gibi görünüyor; ve java8 yeni bir şey gibi görünüyor; ve teşekkürler! :)
::
Sözdizimi Java 8'de yenidir ve lambda'nın kestirme bir biçimi olan bir "yöntem başvurusu" anlamına gelir. Daha fazla bilgi için buraya bakın: docs.oracle.com/javase/tutorial/java/javaOO/…
iterator
geliyor çözülmemiş bir semboldür
iterator
.
Bir yineleyiciyi aşağıdaki gibi yeni bir listeye kopyalayabilirsiniz:
Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
copy.add(iter.next());
Bu, listenin dize içerdiğini varsayar. Bir listeyi bir yineleyiciden yeniden oluşturmanın daha hızlı bir yolu yoktur, elle gezdirmek ve her bir öğeyi uygun türden yeni bir listeye kopyalamak zorunda kalırsınız.
DÜZENLE :
Aşağıda, yineleyiciyi yeni bir listeye güvenli bir şekilde kopyalamak için genel bir yöntem verilmiştir:
public static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Şöyle kullanın:
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
Ve arasında bir fark olduğunu unutmayın Iterator
.
Bir paranız varsa Iterable
, Java 8 ile bu çözümü kullanabilirsiniz:
Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
Bildiğim gibi örnek Collectors.toList()
oluşturur ArrayList
.
Aslında bence, bir satırda da iyi görünüyor.
Örneğin List<Element>
, bazı yöntemlerden geri dönmeniz gerekiyorsa :
return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
Iterable
iterator
. Bunlar tamamen farklı.
Iterator
bir karşı arkasını tek kullanım Iterable
kullanarak () -> iterator
. Bu, bu gibi durumlarda yararlı olabilir, ancak önemli şeyi tekrar vurgulamama izin verin: Bu yöntemi yalnızca tek bir kullanım Iterable
kabul edilebilirse kullanabilirsiniz . iterable.iterator()
Birden fazla çağrı yapmak beklenmedik sonuçlar verecektir. Yukarıdaki cevap daha sonraIterator<Element> iterator = createIterator();
List<Element> array = StreamSupport.stream(((Iterable<Element>) () -> iterable).spliterator(), false).collect(toList());
Ayrıca jenerikleri desteklemese de IteratorUtils
Apache ortak koleksiyonlarından da kullanabilirsiniz :
List list = IteratorUtils.toList(iterator);
Sade Java 8 ile oldukça özlü bir çözüm 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 )
Java 8'de de yeni olanların çok daha özlü olduğunu söyleyebilirim . Liste değişkeninin içine Collector
itilmesi, a Stream
ve a tarafından desteklenmesi gerektiğinden, bu durumda okunabilirliği artırmaz Spliterator
.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Deneyin StickyList
gelen Cactoos :
List<String> list = new StickyList<>(iterable);
Feragatname: Geliştiricilerden biriyim.
Iterable
! =Iterator
Sadece bariz görünen bir çözüm işaret etmek istiyorum DEĞİL olacaktır çalışır:
Liste listesi = Stream.generate (iterator :: next) .Yağlar (Collectors.toList ());
Çünkü Stream#generate(Supplier<T>)
sadece sonsuz akışlar yaratabilir, argümanının atmasını beklemez NoSuchElementException
( Iterator#next()
sonunda yapacak olan budur).
Eğer Iterator → Akış → Liste yolu seçiminizse xehpuk'un cevabı kullanılmalıdır.
google guava kullanın !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
Burada bu durumda mümkün olan en hızlı yolu istiyorsanız o zaman for loop
daha iyidir.
Bir numune sayısı üzerinden yineleyici 10,000 runs
alır 40 ms
döngü alır için gibi olduğu2 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));
Bu, listenin dize içerdiğini varsayar.
for
döngü kullanmak ve bir listenin öğelerine erişmek get(i)
bir yineleyici kullanmaktan daha hızlıdır ... ancak OP'nin istediği bu değildi, özellikle bir yineleyicinin girdi olarak verildiğini belirtti .
get(int)
döngü yalnızca 1m girişlerinin 100k bakıyoruz. Bu döngüyü değiştirirseniz, it.size()
bu 2 yöntemin aynı hıza yakın olduğunu görürsünüz. Genel olarak bu tür java hız testleri sınırlı gerçek yaşam performansı bilgileri sağlar ve şüpheyle bakılmalıdır.