Як я можу створити потік з масиву?


133

В даний час, коли мені потрібно створити потік з масиву, я це роблю

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

Чи існує якийсь прямий спосіб створити потік з масиву?

Відповіді:


201

Ви можете використовувати Arrays.stream Npr

Arrays.stream(array);

Ви також можете використовувати, Stream.ofяк згадує @fge, як виглядає

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

Але примітка Stream.of(intArray)повернеться, Stream<int[]>тоді як Arrays.stream(intArr)повернеться, IntStreamякщо ви передасте масив типу int[]. Тож у двох словах для примітивів типу можна спостерігати різницю між двома методами Напр

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

IntStream stream2 = Arrays.stream(arr); 

Коли ви Arrays.streamпередаєте примітивний масив до , викликається наступний код

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

і при передачі примітивного масиву Stream.ofвикликається наступний код

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

Отже, ви отримуєте різні результати.

Оновлено : Як зазначає коментар Stuart Marks . Перегрупування піддіапазону Arrays.streamбажано використовувати, Stream.of(array).skip(n).limit(m)оскільки перше призводить до розміру потоку SIZED, тоді як останнього немає. Причина полягає в тому, що limit(m)не знає , є чи розмір м або менше , ніж т, в той час як Arrays.streamробить перевірку діапазону і знає точний розмір потоку Ви можете прочитати вихідний код для реалізації потоку повернутої Arrays.stream(array,start,end) тут , в той час як для потоку реалізація повертається Stream.of(array).skip().limit()IS в рамках цього методу .


9
Ця відповідь краща, оскільки Arrays.streamє всі перевантажені випадки для примітивних масивів. Тобто Stream.of(new int[]{1,2,3})дасть вам, Stream<int[]>тоді як Arrays.streamповерне вам IntStream, мабуть, те, що ви хочете. Тож +1
user2336315

3
@Dima Я думаю, це питання смаку. Я маю на увазі, що краще в певному сенсі Stream.ofможе принести вам кілька сюрпризів (наприклад, коли ви дзвоните Arrays.asListз примітивним масивом і коли люди очікують List<Integer>зворотного зв'язку) :-)
user2336315

3
Arrays.streamпідтримує потокове діапазон масиву, який IntStream.ofне відповідає. На відміну від цього , Stream.ofє найкращим вибором , якщо ви хочетеStream<int[]> розміру 1...
Хольгер

4
@Dima Перенавантаження піддіапазону Arrays.streamбажано використовувати, Stream.of(array).skip(n).limit(m)оскільки перше призводить до розміру потоку SIZED, тоді як останнього немає. Причина полягає в тому, що limit(m)невідомо, розмір mчи менший m, тоді як Arrays.streamдіапазон перевіряє і знає точний розмір потоку.
Стюарт відзначає

6
Для читачів, зацікавлених у тому, щоб ця маленька драма була завершена, Arrays.stream(array,start,end)повертає Streamреалізацію, реалізація якої знаходиться тут , тоді як Stream.of(array).skip().limit()повертає Streamреалізацію, реалізація якої знаходиться в рамках цього методу .
Стюарт відзначає

43

Альтернатива рішення @ sol4me:

Stream.of(theArray)

З різниці між цим і Arrays.stream(): це має значення, якщо ваш масив примітивного типу. Наприклад, якщо ви робите:

Arrays.stream(someArray)

де someArrayє long[], воно поверне a LongStream. Stream.of()з іншого боку, поверне a Stream<long[]>з одним елементом.


1
@Dima впевнено, але Arrays.stream()працює і для цього
fge

2
Ну, що стосується потоків, зручності! Немає необхідності телефонувати, *Stream.of()коли ви маєте Arrays.stream()справу з примітивними масивами. А що стосується того, що масиви не є реальними об'єктами, ну це - Java, так це вже з 1.0, і так справляйтеся з цим; замислюватися над цим нічого не допомагає
fge

2
@Dima і так твоє; ви вважаєте, що це Arrays.stream()не зручно, я вважаю це зручним. Достатньо сказано.
fge

2
@Dima так, я вважаю ваш аргумент, який *Stream.of()зручніше бути помилковим; тому що це питання уподобань . Я віддаю перевагу Arrays.stream()таким випадкам, що робить це неправильним як загальне правило, яке Stream.of()є більш зручним (алгебра Пеано).
fge

3
@Dima: це питання переваги. Відмінності настільки неймовірно крихітні, що це зовсім не має значення. Більш конкретно: різниця в декількох символах - це нічого . Додатковим імпортом до пакету всередині стандартних бібліотек є нічого . І дійсно, створити масив замість varargs вручну - це нічого .
Jeroen Vannevel

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

Або, якщо у вас вже є масив, ви також можете це зробити

Stream.of(array) 

Для примітивних типів використовують IntStream.ofабо LongStream.ofін.


Що я не розумію, це те, що, коли int[]можна передати метод, що приймає varargs, чому б не Stream.of(intArray)створити Stream<Integer>замість Stream<int[]>? Також, чи є якісь технічні міркування, чому існують спеціалізовані класи Stream для примітивів?
asgs

1
Примітиви на Java - дивні звірі. int[]не так, як інші масиви. Це не підклас Object[], але це підклас Object. Отже, коли ви передаєте його Stream.of, він приймається як Objectпараметр, і ви отримуєте потік int[]. Це одна з причин мати спеціалізовані класи для примітивних - якби ви не створювали потоки з примітивних масивів, було б досить болісно. Інша причина полягає в тому, що спеціалізовані заняття є більш ефективними, тому що не потрібно вимагати Objectнакладних витрат від боксу (перетворюючись intна те, Integerщоб це виглядало як звичайні об'єкти).
Діма

Так, оскільки int[]це є Object, він би відповідав перевантаженому методу, of(T t)а значить, він повертається Stream<int[]>. Отже, теоретично, якби цей метод не був доступний, ми отримали б Stream<Integer>взамін? а може, це призводить до помилки компіляції, оскільки він не зміг знайти метод відповідності? тобто int[]не можна трактувати якT...
asgs

1
Ні, ми все одно так би не дійшли Stream<Integer>, тому Stream.of(t ... T) що все одно збігались би так само.
Діма

0

Ви можете зробити це також методом низького рівня, який має паралельний варіант:

Оновлення: використовуйте повний array.length (не довжина - 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

Ви можете використовувати Arrays.stream:

Arrays.stream (масив); 

Це забезпечує тип повернення пари на основі типу вхідного масиву, якщо його String []потім повернути Stream<String>, якщо int []потім повернутиIntStream

Коли ви вже знаєте масив типу введення, тоді добре використовувати конкретний тип, наприклад для типу введення int[]

 IntStream.of (масив); 

Це повертає Intstream.

У першому прикладі Java використовує метод overloadingдля пошуку конкретного методу на основі типів введення, тоді як, як і у другому, ви вже знаєте тип введення та викликаєте конкретний метод.


0

рідко зустрічається, але це найпростіший шлях

Stream.Builder<String> builder = Stream.builder();
for( int i = 0; i < array.length; i++ )
  builder.add( array[i] );
Stream<String> stream = builder.build();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.