Câu trả lời:
Sử dụng tốt hơn một thư viện như Guava :
import com.google.common.collect.Lists;
Iterator<Element> myIterator = ... //some iterator
List<Element> myList = Lists.newArrayList(myIterator);
Một ví dụ khác về ổi:
ImmutableList.copyOf(myIterator);
hoặc Bộ sưu tập Apache Commons :
import org.apache.commons.collections.IteratorUtils;
Iterator<Element> myIterator = ...//some iterator
List<Element> myList = IteratorUtils.toList(myIterator);
Trong Java 8, bạn có thể sử dụng forEachRemainingphương thức mới đã được thêm vào Iteratorgiao diện:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
::gì tên đó là gì dường như một tham chiếu trực tiếp đến list.add (); và dường như cũng có một số điều mới java8; và cảm ơn! :)
::Cú pháp là mới trong Java 8 và nó đề cập đến một "tham chiếu phương thức", đây là một dạng tốc ký của lambda. Xem tại đây để biết thêm thông tin: docs.oracle.com/javase/tutorial/java/javaOO/ mẹo
iteratorđến đó là một biểu tượng chưa được giải quyết
iterator.
Bạn có thể sao chép một iterator vào một danh sách mới như thế này:
Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
copy.add(iter.next());
Đó là giả sử rằng danh sách có chứa chuỗi. Thực sự không có cách nào nhanh hơn để tạo lại danh sách từ một trình vòng lặp, bạn bị mắc kẹt với việc duyệt nó bằng tay và sao chép từng phần tử vào một danh sách mới của loại thích hợp.
BIÊN TẬP :
Đây là một phương pháp chung để sao chép một trình vòng lặp vào một danh sách mới theo cách an toàn kiểu:
public static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Sử dụng nó như thế này:
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]
Lưu ý có một sự khác biệt giữa Iterablevà Iterator.
Nếu bạn có một Iterable, thì với Java 8, bạn có thể sử dụng giải pháp này:
Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
Theo tôi biết Collectors.toList()tạo ra ArrayListví dụ.
Trên thực tế theo ý kiến của tôi, nó cũng có vẻ tốt trong một dòng.
Ví dụ: nếu bạn cần quay lại List<Element>từ một số phương thức:
return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
Iterable iterator. Chúng hoàn toàn khác nhau.
Iteratortrở lại thành một lần sử dụng Iterable bằng cách sử dụng () -> iterator. Điều này có thể hữu ích trong các tình huống như thế này, nhưng hãy để tôi nhấn mạnh điều quan trọng một lần nữa: Bạn chỉ có thể sử dụng phương pháp này nếu một lần sử dụng Iterable được chấp nhận. Gọi iterable.iterator()nhiều lần sẽ mang lại kết quả bất ngờ. Câu trả lời trên sau đó trở thànhIterator<Element> iterator = createIterator(); List<Element> array = StreamSupport.stream(((Iterable<Element>) () -> iterable).spliterator(), false).collect(toList());
Bạn cũng có thể sử dụng IteratorUtilstừ các bộ sưu tập chung của Apache , mặc dù nó không hỗ trợ chung chung:
List list = IteratorUtils.toList(iterator);
Giải pháp khá súc tích với Java 8 đơn giản bằng cách sử dụng 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 ), cũng mới trong Java 8, ngắn gọn hơn nhiều. Đẩy biến danh sách vào Collectorkhông cải thiện khả năng đọc trong trường hợp này, vì nó phải được hỗ trợ bởi a Streamvà a Spliterator.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Hãy thử StickyListtừ Cactoos :
List<String> list = new StickyList<>(iterable);
Tuyên bố miễn trừ trách nhiệm: Tôi là một trong những nhà phát triển.
Iterable! =Iterator
Tôi chỉ muốn chỉ ra một giải pháp dường như rõ ràng sẽ KHÔNG hiệu quả:
Danh sách danh sách = Stream.generate (iterator :: next) .collect (Collector.toList ());
Đó là bởi vì chỉ Stream#generate(Supplier<T>)có thể tạo ra các luồng vô hạn, nên nó không hy vọng đối số của nó sẽ bị ném NoSuchElementException(đó là điều Iterator#next()sẽ làm cuối cùng).
Thay vào đó, nên sử dụng câu trả lời của xehpuk nếu Iterator → Stream → List list là lựa chọn của bạn.
sử dụng ổi google !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
Ở đây trong trường hợp này nếu bạn muốn cách nhanh nhất có thể thì for looptốt hơn.
Trình vòng lặp trên một cỡ mẫu 10,000 runssẽ lấy 40 mstrong đó như vòng lặp mất2 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));
Đó là giả sử rằng danh sách có chứa chuỗi.
forvòng lặp và truy cập các phần tử của danh sách get(i)nhanh hơn so với sử dụng trình lặp ... nhưng đó không phải là điều OP yêu cầu, ông đặc biệt đề cập rằng trình lặp được đưa ra làm đầu vào.
get(int)vòng lặp bạn chỉ nhìn vào 100k trong số 1m mục. Nếu bạn thay đổi vòng lặp đó thành it.size()bạn sẽ thấy rằng 2 phương thức này gần với cùng tốc độ. Nói chung, các loại kiểm tra tốc độ java này cung cấp thông tin hiệu suất thực tế hạn chế và nên được xem xét một cách hoài nghi.