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 forEachRemaining
phương thức mới đã được thêm vào Iterator
giao 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 Iterable
và 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 ArrayList
ví 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.
Iterator
trở 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 IteratorUtils
từ 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 Collector
khô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 Stream
và a Spliterator
.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Hãy thử StickyList
từ 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 loop
tốt hơn.
Trình vòng lặp trên một cỡ mẫu 10,000 runs
sẽ lấy 40 ms
trong đó 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.
for
vò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.