Como posso criar um fluxo a partir de uma matriz?

133

Atualmente, sempre que preciso criar fluxo a partir de uma matriz, eu faço

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

Existe alguma maneira direta de criar fluxo a partir de uma matriz?

adam.kubi
fonte

Respostas:

201

Você pode usar Arrays.stream Eg

Arrays.stream(array);

Você também pode usar Stream.ofcomo mencionado pelo @fge, que parece

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

Mas note Stream.of(intArray)que retornará Stream<int[]>enquanto Arrays.stream(intArr)retornará, IntStreamdesde que você passe uma matriz do tipo int[]. Então, em poucas palavras, para o tipo de primitivos, você pode observar a diferença entre 2 métodos.

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

IntStream stream2 = Arrays.stream(arr); 

Quando você passa a matriz primitiva para Arrays.stream, o código a seguir é chamado

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

e quando você passa a matriz primitiva para Stream.ofo código a seguir, é chamado

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

Portanto, você obtém resultados diferentes.

Atualizado : como mencionado por Stuart Marks comment A sobrecarga de subintervalos Arrays.streamé preferível ao uso, Stream.of(array).skip(n).limit(m)porque o primeiro resulta em um fluxo SIZED, enquanto o último não. O motivo é que limit(m)não se sabe se o tamanho é m ou menor que m, enquanto Arrays.streamo range verifica e sabe o tamanho exato do fluxo Você pode ler o código-fonte para a implementação do fluxo retornado por Arrays.stream(array,start,end) aqui , enquanto que para a implementação do fluxo retornado por Stream.of(array).skip().limit()é dentro deste método .

sol4me
fonte
9
Essa resposta é melhor porque Arrays.streamtem todos os casos sobrecarregados para matrizes primitivas. Ou seja Stream.of(new int[]{1,2,3}), você fornecerá um Stream<int[]>considerando Arrays.stream, o IntStreamque provavelmente será o que você deseja. Então +1
user2336315
3
@ Dima Eu acho que é uma questão de gosto. Quero dizer melhor em um sentido Stream.ofpoderia dar-lhe algumas surpresas (como quando você chamar Arrays.asListcom uma matriz primitiva e que as pessoas esperam uma List<Integer>volta) :-)
user2336315
3
Arrays.streamsuporta streaming de um intervalo da matriz, o que IntStream.ofnão. Em contraste, Stream.ofé a melhor escolha se você quer um Stream<int[]>de tamanho 1...
Holger
4
@Dima A sobrecarga de subintervalos Arrays.streamé preferível ao uso, Stream.of(array).skip(n).limit(m)porque o primeiro resulta em um fluxo SIZED, enquanto o último não. O motivo é que limit(m)não se sabe se o tamanho é mou menor que m, enquanto Arrays.streamo range verifica e sabe o tamanho exato do fluxo.
Stuart Marks
6
Para os leitores interessados ​​em ver esse pequeno drama concluído, Arrays.stream(array,start,end)retorna a Streamcuja implementação está aqui , enquanto Stream.of(array).skip().limit()retorna a Streamcuja implementação está dentro desse método .
Stuart Marks
43

Alternativa à solução da @ sol4me:

Stream.of(theArray)

Da diferença entre this e Arrays.stream(): faz diferença se sua matriz é de um tipo primitivo. Por exemplo, se você fizer:

Arrays.stream(someArray)

onde someArrayé a long[], retornará a LongStream. Stream.of(), por outro lado, retornará a Stream<long[]>com um único elemento.

fge
fonte
1
@Dima certeza, mas Arrays.stream()obras para isso também
fge
2
Bem, quanto aos riachos, conveniência! Não é necessário ligar *Stream.of()quando você precisar Arrays.stream()ao lidar com matrizes primitivas. E quanto a matrizes não serem objetos reais, bem, isso é Java, esse tem sido o caso desde a versão 1.0, então lide com isso; remoendo isso ajuda nada
fge
2
@Dima e assim é o seu; você considera Arrays.stream()não ser conveniente, eu considero que seja conveniente. Disse o suficiente.
fge 11/01
2
@ Dima sim, acho seu argumento *Stream.of()mais conveniente para ser falacioso; porque é uma questão de preferências . Prefiro Arrays.stream()para esses casos, o que torna errado como regra geral Stream.of()mais conveniente (álgebra de Peano).
fge 11/01
3
@ Dima: é uma questão de preferência. As diferenças são tão incrivelmente pequenas que não importam nada. Mais especificamente: a diferença de alguns caracteres não é nada . Uma importação adicional para um pacote dentro das bibliotecas padrão não é nada . E realmente, criar manualmente uma matriz em vez de uma sobrecarga de varargs não é nada .
Jeroen Vannevel
14
Stream.of("foo", "bar", "baz")

Ou, se você já possui uma matriz, também pode fazer

Stream.of(array) 

Para tipos primitivos, use IntStream.ofou LongStream.ofetc.

Dima
fonte
O que não entendo é que, quando um int[]pode ser passado para um método que aceita varargs, por que não Stream.of(intArray)produzir um em Stream<Integer>vez de Stream<int[]>? Além disso, existe algum raciocínio técnico sobre o motivo de existirem classes Stream especializadas para primitivas?
asgs
1
As primitivas Java são bestas estranhas. int[]não é como outras matrizes. Não é uma subclasse de Object[], mas é uma subclasse de Object. Então, quando você passa para Stream.of, ele é tomado como Objectparâmetro, e você recebe um fluxo de int[]. Essa é uma das razões para ter aulas especializadas em primitivas - se você não criar fluxos a partir de matrizes primitivas seria muito doloroso. A outra razão, é que as classes especializadas são mais eficientes, porque o não precisa incorrer na Objectsobrecarga do boxe (convertendo intpara Integerfazer parecer como objetos normais).
Dima
Ah, já que int[]é um Object, ele corresponderia ao método sobrecarregado of(T t)e, portanto, retornará Stream<int[]>. Então, teoricamente falando, se esse método não estivesse disponível, teríamos o Stream<Integer>retorno? ou talvez isso resulte em um erro de compilação porque não foi possível encontrar o método correspondente? ou seja, int[]não pode ser tratado comoT...
asgs
1
Não, ainda não seríamos Stream<Integer>assim, porque Stream.of(t ... T) ainda corresponderiam da mesma maneira.
Dima
0

Você pode fazer isso também pelo método de baixo nível, que tem a opção paralela:

Atualização: Use array.length completo (não comprimento - 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
fonte
0

Você pode usar Arrays.stream:

Arrays.stream (matriz); 

Isso garante o tipo de retorno de vapor com base no tipo de entrada do seu array, se String []então retornar Stream<String>, se int []retornarIntStream

Quando você já conhece a matriz de tipos de entrada, é bom usar uma matriz específica, como para o tipo de entrada int[]

 IntStream.of (matriz); 

Isso retorna o Intstream.

No primeiro exemplo, Java usa o método overloadingpara localizar um método específico com base nos tipos de entrada, enquanto no segundo você já conhece o tipo de entrada e chama o método específico.

vipul patel
fonte
0

raramente visto, mas esta é a maneira mais direta

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