Làm thế nào tôi có thể tạo một luồng từ một mảng?


133

Hiện tại bất cứ khi nào tôi cần tạo luồng từ một mảng, tôi đều làm

String[] array = {"x1", "x2"};
Arrays.asList(array).stream();

Có một số cách trực tiếp để tạo luồng từ một mảng?

Câu trả lời:


201

Bạn có thể sử dụng Arrays.stream Eg

Arrays.stream(array);

Bạn cũng có thể sử dụng Stream.ofnhư được đề cập bởi @fge, trông giống như

public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}

Nhưng lưu ý Stream.of(intArray)sẽ trở lại Stream<int[]>trong khi Arrays.stream(intArr)sẽ trả về IntStreamcung cấp cho bạn vượt qua một loạt các loại int[]. Vì vậy, tóm lại cho loại nguyên thủy, bạn có thể quan sát sự khác biệt giữa 2 phương thức Eg

int[] arr = {1, 2};
Stream<int[]> arr1 = Stream.of(arr);

IntStream stream2 = Arrays.stream(arr); 

Khi bạn chuyển mảng nguyên thủy sang Arrays.stream, đoạn mã sau được gọi

public static IntStream stream(int[] array) {
    return stream(array, 0, array.length);
}

và khi bạn truyền mảng nguyên thủy cho Stream.ofđoạn mã sau được gọi

 public static<T> Stream<T> of(T t) {
     return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
 }

Do đó bạn nhận được kết quả khác nhau.

Đã cập nhật : Như đã đề cập bởi nhận xét của Stuart Marks Quá tải phụ Arrays.streamđược ưu tiên sử dụng Stream.of(array).skip(n).limit(m)vì các kết quả trước trong luồng SIZED trong khi điều sau thì không. Lý do là vì limit(m)không biết kích thước là m hay nhỏ hơn m, trong khi Arrays.streamkiểm tra phạm vi và biết kích thước chính xác của luồng Bạn có thể đọc mã nguồn để thực hiện luồng được trả về Arrays.stream(array,start,end) tại đây , trong khi thực hiện luồng được trả về Stream.of(array).skip().limit()là trong phương pháp này .


9
Câu trả lời này là tốt hơn bởi vì Arrays.streamcó tất cả các trường hợp quá tải cho mảng nguyên thủy. Tức là Stream.of(new int[]{1,2,3})sẽ cung cấp cho bạn Stream<int[]>trong khi Arrays.streamsẽ cung cấp cho bạn một IntStreamcái mà có lẽ là những gì bạn muốn. Vì vậy, +1
user2336315

3
@Dima Tôi đoán đó là vấn đề của hương vị. Ý tôi là tốt hơn theo nghĩa nào đó Stream.ofcó thể mang đến cho bạn một số điều ngạc nhiên (như khi bạn gọi Arrays.asListvới một mảng nguyên thủy và mọi người mong đợi sự List<Integer>trở lại) :-)
user2336315

3
Arrays.streamhỗ trợ truyền phát một loạt các mảng, điều IntStream.ofnày không. Ngược lại, Stream.oflà sự lựa chọn tốt hơn nếu bạn muốn một Stream<int[]>kích thước 1...
Holger

4
@Dima Quá tải phụ Arrays.streamđược ưu tiên sử dụng Stream.of(array).skip(n).limit(m)vì kết quả trước trong luồng SIZED trong khi luồng sau thì không. Lý do là limit(m)không biết kích thước lớn mhơn hoặc nhỏ hơn m, trong khi Arrays.streamđó phạm vi kiểm tra và biết kích thước chính xác của luồng.
Stuart Marks

6
Đối với những độc giả quan tâm đến việc xem bộ phim nhỏ này được kết luận, Arrays.stream(array,start,end)trả về một Streamngười thực hiện ở đây , trong khi Stream.of(array).skip().limit()trả lại một Streamngười thực hiện trong phương thức này .
Stuart Marks

43

Thay thế cho giải pháp của @ sol4me:

Stream.of(theArray)

Sự khác biệt giữa điều này và Arrays.stream(): nó sẽ tạo ra sự khác biệt nếu mảng của bạn thuộc kiểu nguyên thủy. Chẳng hạn, nếu bạn làm:

Arrays.stream(someArray)

đâu someArraylà a long[], nó sẽ trả về a LongStream. Stream.of()mặt khác, sẽ trả về a Stream<long[]>với một phần tử duy nhất.


1
@Dima chắc chắn, nhưng cũng Arrays.stream()hoạt động cho điều đó
fge

2
Vâng, như để stream, thuận tiện! Không cần phải gọi *Stream.of()khi bạn có Arrays.stream()khi xử lý các mảng nguyên thủy. Và đối với các mảng không phải là các đối tượng thực, thì, đây là Java, đây là trường hợp kể từ 1.0 vì vậy hãy giải quyết nó; nghiền ngẫm về điều này chẳng giúp được gì
fge

2
@Dima và bạn cũng vậy; bạn coi là Arrays.stream()không thuận tiện, tôi coi nó là thuận tiện. Đủ nói.
fge

2
@Dima vâng, tôi thấy lập luận của bạn *Stream.of()thuận tiện hơn để trở nên ngụy biện; bởi vì đó là vấn đề sở thích . Tôi thích Arrays.stream()các trường hợp như vậy, điều này làm cho nó sai như một quy tắc chung Stream.of()thuận tiện hơn (đại số Peano).
fge

3
@Dima: đó là vấn đề ưu tiên. Sự khác biệt là cực kỳ nhỏ đến nỗi nó không thành vấn đề. Cụ thể hơn: một sự khác biệt của một vài nhân vật là không có gì . Một nhập khẩu bổ sung cho một gói bên trong các thư viện tiêu chuẩnkhông có gì . Và thực sự, việc tự tạo một mảng thay vì quá tải varargs là không có gì .
Jeroen Vannevel

14
Stream.of("foo", "bar", "baz")

Hoặc, nếu bạn đã có một mảng, bạn cũng có thể làm

Stream.of(array) 

Đối với các loại nguyên thủy sử dụng IntStream.ofhoặc LongStream.ofvv


Điều tôi không hiểu là, khi int[]một phương thức có thể được truyền cho một phương thức chấp nhận varargs, tại sao sẽ không Stream.of(intArray)tạo ra một Stream<Integer>thay thế Stream<int[]>? Ngoài ra, có bất kỳ lý do kỹ thuật tại sao có các lớp Stream chuyên biệt cho người nguyên thủy không?
vào

1
Người nguyên thủy Java là những con thú kỳ lạ. int[]không giống như các mảng khác. Nó không phải là một lớp con của Object[], nhưng nó một lớp con của Object. Vì vậy, khi bạn chuyển nó tới Stream.of, nó được lấy làm Objecttham số, và bạn nhận được một luồng int[]. Đó là một trong những lý do để có các lớp chuyên biệt cho nguyên thủy - nếu bạn không tạo luồng từ mảng nguyên thủy sẽ khá đau đớn. Lý do khác, đó là lớp chuyên là hiệu quả hơn, vì không cần phải chịu các Objectchi phí từ đấm bốc (chuyển đổi intđể Integerlàm cho nó trông giống như đối tượng bình thường).
Dima

Ah, vì int[]là một Object, nó sẽ phù hợp với phương thức quá tải of(T t)và do đó nó trả về Stream<int[]>. Vì vậy, về mặt lý thuyết mà nói, nếu phương pháp này không có sẵn, chúng ta sẽ nhận được Stream<Integer>lợi nhuận? hoặc có thể nó gây ra lỗi biên dịch vì không thể tìm thấy phương thức khớp? tức là int[]không thể được coi làT...
asgs

1
Không, chúng tôi vẫn không hiểu Stream<Integer>theo cách đó, vì Stream.of(t ... T) vẫn phù hợp với cùng một cách.
Dima

0

Bạn cũng có thể thực hiện bằng phương pháp cấp thấp có tùy chọn song song:

Cập nhật: Sử dụng đầy đủ mảng.length (không phải chiều dài - 1).

/** 
 * Creates a new sequential or parallel {@code Stream} from a
 * {@code Spliterator}.
 *
 * <p>The spliterator is only traversed, split, or queried for estimated
 * size after the terminal operation of the stream pipeline commences.
 *
 * @param <T> the type of stream elements
 * @param spliterator a {@code Spliterator} describing the stream elements
 * @param parallel if {@code true} then the returned stream is a parallel
 *        stream; if {@code false} the returned stream is a sequential
 *        stream.
 * @return a new sequential or parallel {@code Stream}
 *
 * <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel)
 */

StreamSupport.stream(Arrays.spliterator(array, 0, array.length), true)

0

Bạn có thể sử dụng Arrays.stream:

Arrays.stream (mảng); 

Điều này đảm bảo loại hơi trả về dựa trên loại đầu vào mảng của bạn nếu String []sau đó trả về Stream<String>, nếu int []sau đó trả vềIntStream

Khi bạn đã biết mảng kiểu đầu vào thì tốt để sử dụng một kiểu cụ thể như kiểu đầu vào int[]

 IntStream.of (mảng); 

Điều này trả về Intux.

Trong ví dụ đầu tiên, Java sử dụng phương thức overloadingđể tìm phương thức cụ thể dựa trên các kiểu đầu vào trong khi ở giây thứ hai bạn đã biết kiểu đầu vào và gọi phương thức cụ thể.


0

hiếm khi nhìn thấy, nhưng đây là cách trực tiếp nhất

Stream.Builder<String> builder = Stream.builder();
for( int i = 0; i < array.length; i++ )
  builder.add( array[i] );
Stream<String> stream = builder.build();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.