2015-08-31 19 views
11

Giả sử bạn muốn truyền các phần tử của một trình lặp; chúng ta hãy sử dụng ví dụ cụ thể về một Scanner, thực hiện Iterator<String>.Cách đơn giản nhất để phát một trình lặp số

đưa ra một Iterator, nói:

// Scanner implements Iterator<String> 
Iterator<String> scanner = new Scanner(System.in); 

Tùy chọn để tạo ra một Stream<String> từ nó là phiền phức:

StreamSupport.stream(
    Spliterators.spliteratorUnknownSize(scanner, Spliterator.ORDERED), false); 

hoặc hơi ngắn gọn hơn, nhưng tù:

StreamSupport.stream(
    ((Iterable<String>)() -> new Scanner(System.in)).spliterator(), false); 

Có phương pháp nhà máy nào đó trong JDK trả về mộtkhôngđược cung cấp một số Iterator<T>?

+1

Bạn bối rối tôi bằng cách nói 'new Scanner (System.in);// nó là một Iterable ' – Holger

+1

Không có cách nào đơn giản hơn nhưng điều này thực sự phổ biến là một cách đơn giản hơn là cần thiết? – Holger

+0

@holger bởi vì 'lớp Máy quét thực hiện Iterator ' và có, tôi thường muốn dòng các yếu tố của một iterator (không chỉ là máy quét tất nhiên, đó chỉ là một ví dụ của một của nó không phải là một bộ sưu tập) – Bohemian

Trả lời

7

Tôi chỉ cần sử dụng Stream.generate(iterator::next). Vâng, đó là một dòng vô hạn, nhưng như vậy là máy quét từ System.in, trừ khi bạn biết có bao nhiêu dòng bạn đang yêu cầu cho trong trường hợp này rất dễ dàng, đủ để sử dụng

Stream.generate(iterator::next).limit(numLines); 

Điều này ngăn cản các iterator từ phải được lặp lại hai lần (một lần làm trình lặp, một lần là luồng).

Nếu bạn cần một dòng suối nhỏ mà không biết làm thế nào lớn nó sẽ được, nhưng không muốn lộn xộn mã của bạn chỉ cần tạo một phương pháp hữu ích mà sẽ đưa một cách rõ ràng một Iterable<T>:

public static <T> Stream<T> stream(Iterable<T> it){ 
    return StreamSupport.stream(it.spliterator(), false); 
} 

Nó kết thúc lên được nhiều hơn dễ đọc hơn là cố gắng nhồi nhét nó trên cùng một dòng, và sau đó bạn chỉ có thể gọi stream(()->iterator); hoặc stream(()->new Scanner(System.in));

bạn có thể thêm các phương pháp tiện lợi thứ hai dễ dàng đủ, quá:

public static <T> Stream<T> stream(Iterator<T> it){ 
    return stream(()->it); 
} 

cho phép bạn gọi stream(iterator); hoặc stream(new Scanner(System.in));

Mặc dù, nếu tôi được là sẽ đọc System.in thành một dòng suối, tôi có thể sử dụng một Reader chứ không phải là một máy quét anyway:

return new BufferedReader(new InputStreamReader(System.in)).lines(); 
Các vấn đề liên quan