2015-06-06 18 views
15

Tôi muốn triển khai Stream<T>.Làm cách nào để triển khai luồng Java?

Tôi không muốn chỉ sử dụng implements Stream<T>, bởi vì tôi sẽ phải triển khai hàng tấn phương pháp.

Điều này có tránh được không?

Để cụ thể hơn, làm thế nào tôi có thể truyền t1, t2t3 ví dụ:

class Foo<T> { 
    T t1, t2, t3; 

    Foo(T t1, T t2, T t3) { 
     this.t1 = t1; 
     this.t2 = t2; 
     this.t3 = t3; 
    } 
} 
+8

'Stream.of (t1 , t2, t3) '. –

+3

['Stream.builder'] (https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#builder--) – fabian

Trả lời

24

thực hiện tiêu chuẩn của JDK của Stream là lớp nội java.util.stream.ReferencePipeline, bạn không thể khởi tạo nó trực tiếp.

Thay vào đó bạn có thể sử dụng java.util.stream.Stream.builder(), java.util.stream.StreamSupport.stream(Spliterator<T>, boolean) và khác nhau 1, 2 phương pháp nhà máy tĩnh khác để tạo ra một thể hiện của việc thực hiện mặc định.

Sử dụng trình phân tách có lẽ là phương pháp mạnh mẽ nhất vì nó cho phép bạn cung cấp các đối tượng một cách lười biếng trong khi cũng cho phép song song hiệu quả nếu nguồn của bạn có thể được chia thành nhiều phần. Ngoài ra, bạn cũng có thể chuyển đổi luồng trở lại thành trình tách biệt, đưa chúng vào trình tách biệt tùy chỉnh và sau đó chuyển đổi chúng thành luồng nếu bạn cần triển khai các hoạt động trung gian trạng thái riêng của mình - ví dụ: do thiếu sót trong các API tiêu chuẩn - vì hầu hết các ops trung gian có sẵn are not allowed to be stateful.
Xem this SO answer để biết ví dụ.

Về nguyên tắc, bạn có thể viết triển khai giao diện luồng của riêng mình, nhưng điều đó sẽ khá tẻ nhạt.

8

Bạn thường không cần phải viết lớp luồng của riêng mình. Thay vào đó bạn có thể tạo luồng theo các phương thức hiện có. Ví dụ, ở đây là làm thế nào để tạo ra một dòng giá trị 1, 100:

AtomicInteger n = new AtomicInteger(0); 
    Stream<Integer> stream = Stream.generate(() -> n.incrementAndGet()).limit(100); 

nên ở đây chúng tôi tạo ra một dòng vô hạn các số nguyên: 1, 2, 3, .... sau đó chúng tôi sử dụng limit(100) trên luồng vô hạn đó để lấy lại luồng 100 phần tử.

Để rõ ràng, nếu bạn muốn một luồng các số nguyên (trong khoảng thời gian cố định), bạn nên sử dụng IntStream.range(). Đây chỉ là một ví dụ để chỉ ra cách các luồng có thể được xác định bằng cách sử dụng Stream.generate() mang lại cho bạn sự linh hoạt hơn vì nó cho phép bạn sử dụng logic tùy ý để xác định các phần tử của hơi nước.

+2

' IntStream.range (0,100) ' sẽ hiệu quả hơn trong trường hợp này. – the8472

+0

Điều này có thể được rút ngắn thành 'Stream.generate (n :: incrementAndGet) .limit (100)' –

+0

Sử dụng 'n :: getAndIncrement' nếu bạn muốn luồng bắt đầu ở 0. –

3

Những người khác đã trả lời cách cung cấp triển khai Stream đa năng. Về yêu cầu cụ bạn, chỉ cần làm điều này:

class Foo<T> { 

    T t1, t2, t3; 

    Foo(T t1, T t2, T t3) { 
     this.t1 = t1; 
     this.t2 = t2; 
     this.t3 = t3; 
    } 

    Stream<T> stream() { 
     return Stream.of(t1, t2, t3); 
    } 
} 
6

Nếu bạn đang muốn làm cho suối của riêng bạn bởi vì bạn muốn close() logic tùy chỉnh, giải pháp đơn giản nhất là để tạo ra một Stream từ một Iterator, và gọi onClose(Runnable) .Ví dụ, để dòng từ một Reader qua Jackson:

MappingIterator<?> values = objectMapper.reader(type).readValues(reader); 
return StreamSupport 
     .stream(Spliterators.spliteratorUnknownSize(values, Spliterator.ORDERED), false) 
     .onClose(() -> { 
      try { 
       reader.close(); 
      } catch (IOException e) { 
       throw new RuntimeException(e); 
      } 
     }); 
1

Vì lợi ích của sự hoàn chỉnh, vì tôi không tìm thấy điều này trực tiếp trong những câu trả lời ở đây trên SO: Nếu bạn muốn chuyển đổi một Iterator hiện có thành một Stream (ví dụ, bởi vì bạn muốn tạo ra các yếu tố liên tiếp), sử dụng này:

StreamSupport.stream(
    Spliterators.spliterator(myIterator, /* initial size*/ 0L, Spliterator.NONNULL), 
    /* not parallel */ false); 

tôi thấy điều này một chút khó khăn để tìm, như bạn cần phải biết StreamSupport, Spliterators và Spliterator

Các vấn đề liên quan