Как я могу создать поток из массива?

133

В настоящее время всякий раз, когда мне нужно создать поток из массива, я делаю

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

Есть ли какой-нибудь прямой способ создать поток из массива?

adam.kubi
источник

Ответы:

201

Вы можете использовать Arrays.stream Например

Arrays.stream(array);

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

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

Но note 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);
 }

Следовательно, вы получите разные результаты.

Обновлено : как отмечалось в комментарии Стюарта Маркса Перегрузка поддиапазона Arrays.streamпредпочтительнее, чем использование, Stream.of(array).skip(n).limit(m)поскольку первое приводит к потоку SIZED, а второе - нет. Причина в том, что limit(m)он не знает, является ли размер m или меньше m, в то время Arrays.streamкак диапазон проверяет и знает точный размер потока. Вы можете прочитать исходный код для реализации потока, возвращаемой Arrays.stream(array,start,end) здесь , тогда как для реализации потока, возвращенной Stream.of(array).skip().limit()is в рамках этого метода .

sol4me
источник
9
Этот ответ лучше, потому что Arrays.streamимеет все перегруженные случаи для примитивных массивов. Т.е. Stream.of(new int[]{1,2,3})даст вам какое- Stream<int[]>то время, а Arrays.streamвернет вам то, IntStreamчто, вероятно, вы хотите. Так что +1
user2336315
3
@ Дима Я думаю, это дело вкуса. Я имею в виду, что в некотором смысле лучше Stream.ofможет преподнести вам некоторые сюрпризы (например, когда вы звоните Arrays.asListс примитивным массивом и что люди ожидают List<Integer>
ответа
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)возвращает a Stream, реализация которого находится здесь , тогда как Stream.of(array).skip().limit()возвращает a Stream, реализация которого находится внутри этого метода .
Стюарт Маркс
43

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

Stream.of(theArray)

Разница между этим и Arrays.stream(): имеет значение, если ваш массив имеет примитивный тип. Например, если вы делаете:

Arrays.stream(someArray)

где someArrayэто long[], он будет возвращать LongStream. Stream.of()с другой стороны, вернет a Stream<long[]>с одним элементом.

FGE
источник
1
@ Дима, конечно, но Arrays.stream()работает и для этого
fge
2
Ну что касается потоков, удобство! Не нужно вызывать, *Stream.of()когда у вас есть Arrays.stream()при работе с примитивными массивами. А что касается массивов, не являющихся реальными объектами, ну, это Java, так было с 1.0, так что разберитесь с этим; размышлять над этим ничего не помогает
fge
2
@Dima и твой; Вы считаете, что это Arrays.stream()не удобно, я считаю, что это удобно. Достаточно сказано.
фг
2
@ Дима, да, я считаю твой аргумент *Stream.of()более удобным, чтобы быть ошибочным; потому что это вопрос предпочтений . Я предпочитаю Arrays.stream()для таких случаев, что делает его неправильным как общее правило, Stream.of()которое более удобно (алгебра Пеано).
фг
3
@Dima: это вопрос предпочтений. Различия настолько малы, что это не имеет значения. Конкретнее: разница в несколько символов ничто . Дополнительный импорт в пакет внутри стандартных библиотек - ничто . И действительно, создание массива вручную вместо перегрузки varargs - ничто .
Йерун Ванневел
14
Stream.of("foo", "bar", "baz")

Или, если у вас уже есть массив, вы также можете сделать

Stream.of(array) 

Для примитивных типов используйте IntStream.ofили LongStream.ofт. Д.

Дима
источник
Что я не понимаю, так это то, что когда int[]метод может быть передан методу, принимающему varargs, почему бы не Stream.of(intArray)создать Stream<Integer>вместо Stream<int[]>? Кроме того, существуют ли технические причины, по которым существуют специализированные классы Stream для примитивов?
просит
1
Примитивы Java - странные звери. int[]не похож на другие массивы. Это не подкласс Object[], но это подкласс Object. Итак, когда вы передаете его Stream.of, он принимается как Objectпараметр, и вы получаете поток int[]. Это одна из причин иметь специализированные классы для примитивов - если бы вы не создавали потоки из примитивных массивов, это было бы довольно болезненно. Другая причина в том, что специализированные классы более эффективны, потому что им не нужно брать на себя Objectнакладные расходы из бокса (преобразование intв, Integerчтобы они выглядели как обычные объекты).
Дима
Ах, так int[]как это Object, он будет соответствовать перегруженному методу of(T t)и, следовательно, он возвращает Stream<int[]>. Итак, теоретически, если бы этот метод не был доступен, мы бы получили Stream<Integer>взамен? или, возможно, это приводит к ошибке компиляции, потому что он не может найти подходящий метод? то есть int[]не может рассматриваться какT...
просит
1
Нет, мы бы так не поступили Stream<Integer>, потому Stream.of(t ... T) что все равно подходили бы так же.
Дима
0

Вы можете сделать это также методом низкого уровня, который имеет параллельную опцию:

Обновление: используйте полную array.length (не 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)
merqlove
источник
0

Вы можете использовать Arrays.stream:

Arrays.stream (массив); 

Это гарантирует возвращаемый тип steam на основе вашего типа ввода массива, если String []затем return Stream<String>, если int []затем возвращаетIntStream

Если вы уже знаете массив типов ввода, тогда лучше использовать определенный тип, например, для типа ввода int[]

 IntStream.of (массив); 

Это возвращает Intstream.

В первом примере Java использует метод overloadingдля поиска конкретного метода на основе типов ввода, в то время как во втором вы уже знаете тип ввода и вызываете конкретный метод.

Vipul Patel
источник
0

редко видел, но это самый прямой путь

Stream.Builder<String> builder = Stream.builder();
for( int i = 0; i < array.length; i++ )
  builder.add( array[i] );
Stream<String> stream = builder.build();
Каплан
источник