¿Cómo puedo crear una secuencia desde una matriz?

133

Actualmente, cada vez que necesito crear una secuencia desde una matriz, lo hago

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

¿Hay alguna forma directa de crear una secuencia desde una matriz?

adam.kubi
fuente

Respuestas:

201

Puedes usar Arrays.stream Eg

Arrays.stream(array);

También puede usar Stream.ofcomo lo menciona @fge, que se ve así

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

Pero note Stream.of(intArray)volverá Stream<int[]>mientras Arrays.stream(intArr)que regresará IntStreamsiempre que pase una matriz de tipos int[]. Entonces, en pocas palabras para los tipos primitivos, puede observar la diferencia entre 2 métodos

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

IntStream stream2 = Arrays.stream(arr); 

Cuando pasa matriz primitiva a Arrays.stream, se invoca el siguiente código

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

y cuando pasa matriz primitiva al Stream.ofsiguiente código se invoca

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

Por lo tanto, obtienes resultados diferentes.

Actualizado : como lo menciona el comentario de Stuart Marks. La sobrecarga de subrango de Arrays.streames preferible a usar Stream.of(array).skip(n).limit(m)porque la primera da como resultado una secuencia TAMAÑO mientras que la segunda no. La razón es que limit(m)no sabe si el tamaño es m o menor que m, mientras Arrays.streamque comprueba el rango y conoce el tamaño exacto de la secuencia. Puede leer el código fuente para la implementación de la secuencia devuelta Arrays.stream(array,start,end) aquí , mientras que para la implementación de la secuencia devuelta Stream.of(array).skip().limit()es dentro de este método .

sol4me
fuente
9
Esta respuesta es mejor porque Arrays.streamtiene todos los casos sobrecargados para matrices primitivas. Es decir, Stream.of(new int[]{1,2,3})le dará un Stream<int[]>mientras Arrays.streamque le devolverá uno IntStreamque probablemente sea lo que desea. Entonces +1
user2336315
3
@Dima, supongo que es cuestión de gustos. Quiero decir, mejor en un sentido Stream.ofpodría darte algunas sorpresas (como cuando llamas Arrays.asListcon una matriz primitiva y que la gente espera una List<Integer>devolución) :-)
user2336315
3
Arrays.streamadmite la transmisión de un rango de la matriz, que IntStream.ofno lo hace. Por el contrario, Stream.ofes la mejor opción si desea un Stream<int[]>tamaño 1...
Holger
44
@Dima La sobrecarga de subrango de Arrays.streames preferible a usar Stream.of(array).skip(n).limit(m)porque la primera da como resultado una secuencia TAMAÑO mientras que la segunda no. La razón es que limit(m)no sabe si el tamaño es mmenor o igual que m, mientras que Arrays.streamhace comprobaciones de rango y conoce el tamaño exacto de la transmisión.
Stuart Marks el
66
Para los lectores que estén interesados ​​en ver concluido este pequeño drama, se Arrays.stream(array,start,end)devuelve una Streamimplementación cuya cuya aplicación está aquí , mientras que se Stream.of(array).skip().limit()devuelve una Streamimplementación cuya implementación está dentro de este método .
Stuart Marks
43

Alternativa a la solución de @ sol4me:

Stream.of(theArray)

De la diferencia entre esto y Arrays.stream(): hace una diferencia si su matriz es de un tipo primitivo. Por ejemplo, si haces:

Arrays.stream(someArray)

donde someArrayes a long[], devolverá unLongStream . Stream.of(), por otro lado, devolverá un Stream<long[]>con un solo elemento.

fge
fuente
1
@Dima seguro, pero también Arrays.stream()funciona para eso
fge
2
Bueno, en cuanto a las transmisiones, ¡conveniencia! No es necesario llamar *Stream.of()cuando tiene Arrays.stream()cuando se trata de matrices primitivas. Y en cuanto a que las matrices no son objetos reales, bueno, esto es Java, este ha sido el caso desde 1.0, así que trátelo; meditar sobre esto no ayuda nada
fge
2
@Dima y también lo es el tuyo; usted considera que Arrays.stream()no es conveniente, yo considero que es conveniente. Basta de charla.
fge
2
@Dima sí, creo que tu argumento *Stream.of()es más conveniente para ser falaz; porque es una cuestión de preferencias . Prefiero Arrays.stream()para tales casos, lo que lo hace incorrecto como una regla general que Stream.of()es más conveniente (álgebra de Peano).
fge
3
@Dima: es una cuestión de preferencia. Las diferencias son tan increíblemente pequeñas que no importa en absoluto. Más específicamente: una diferencia de unos pocos caracteres no es nada . Una importación adicional a un paquete dentro de las bibliotecas estándar no es nada . Y realmente, crear manualmente una matriz en lugar de una sobrecarga de varargs no es nada .
Jeroen Vannevel
14
Stream.of("foo", "bar", "baz")

O, si ya tiene una matriz, también puede hacer

Stream.of(array) 

Para tipos primitivos use IntStream.ofo LongStream.ofetc.

Dima
fuente
Lo que no entiendo es que, cuando int[]se puede pasar a un método que acepta varargs, ¿por qué no se Stream.of(intArray)produce un en Stream<Integer>lugar de Stream<int[]>? Además, ¿hay algún razonamiento técnico por el que hay clases de Stream especializadas para primitivas?
Pregunta el
1
Las primitivas de Java son bestias raras. int[]No es como otras matrices. No es una subclase de Object[], pero es una subclase de Object. Entonces, cuando se lo pasas Stream.of, se toma como el Objectparámetro, y obtienes una secuencia de int[]. Esa es una de las razones para tener clases especializadas para primitivas: si no crearas secuencias a partir de matrices primitivas, sería bastante doloroso. La otra razón es que las clases especializadas son más eficientes, ya que no es necesario incurrir en los Objectgastos generales del boxeo (convertir inta Integerpara que se vean como objetos normales).
Dima
Ah, como int[]es un Object, coincidiría con el método sobrecargado of(T t)y, por lo tanto, vuelve Stream<int[]>. Entonces, teóricamente hablando, si este método no estuviera disponible, ¿habríamos obtenido el Stream<Integer>a cambio? o tal vez resulte en un error de compilación porque no pudo encontrar el método de coincidencia? es decir int[], no puede ser tratado comoT...
pregunta
1
No, aún no lo haríamos de Stream<Integer>esa manera, porque Stream.of(t ... T) aún coincidiría de la misma manera.
Dima
0

También puede hacerlo mediante un método de bajo nivel que tiene una opción paralela:

Actualización: Use full array.length (no 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
fuente
0

Puedes usar Arrays.stream:

Arrays.stream (matriz); 

Esto asegura el tipo de retorno de vapor basado en el tipo de entrada de su matriz si String []luego se devuelve Stream<String>, siint [] luego regresaIntStream

Cuando ya conoces la matriz de tipo de entrada, entonces es bueno usar una específica como tipo de entrada int[]

 IntStream.of (matriz); 

Esto devuelve Intstream.

En el primer ejemplo, Java usa un método overloadingpara encontrar un método específico basado en tipos de entrada, mientras que en el segundo ya conoce el tipo de entrada y el método específico de llamada.

vipul patel
fuente
0

rara vez visto, pero esta es la forma más directa

Stream.Builder<String> builder = Stream.builder();
for( int i = 0; i < array.length; i++ )
  builder.add( array[i] );
Stream<String> stream = builder.build();
Kaplan
fuente