Como converter um Java 8 Stream em uma matriz?


775

Qual é a maneira mais fácil / mais curta de converter um Java 8 Streamem uma matriz?


2
Eu sugiro que você reverta a reversão, pois a pergunta foi mais completa e mostrou que você tentou algo.
skiwi

2
@skiwi Thanks! mas eu pensei que a tentativa de código não realmente adicionar mais informações para a questão, e ninguém gritou "mostrar-nos a sua tentativa" ainda =)

17
@skiwi: Embora eu costumo gritar com as perguntas do tipo "faça minha lição de casa em vez de mim", essa pergunta em particular parece ser mais clara para mim sem qualquer confusão adicional. Vamos mantê-lo arrumado.
Honza Zidek

Você pode encontrar muitas respostas e orientações nos documentos oficiais do pacote: docs.oracle.com/javase/8/docs/api/java/util/stream/…
Christophe Roussy

Respostas:


1168

O método mais fácil é usar o toArray(IntFunction<A[]> generator)método com uma referência de construtor de matriz. Isso é sugerido na documentação da API do método .

String[] stringArray = stringStream.toArray(String[]::new);

O que ele faz é encontrar um método que aceita um número inteiro (o tamanho) como argumento e retorna a String[], que é exatamente o que (uma das sobrecargas de) new String[]faz.

Você também pode escrever o seu IntFunction:

Stream<String> stringStream = ...;
String[] stringArray = stringStream.toArray(size -> new String[size]);

O objetivo do IntFunction<A[]> generatoré converter um número inteiro, o tamanho da matriz, em uma nova matriz.

Código de exemplo:

Stream<String> stringStream = Stream.of("a", "b", "c");
String[] stringArray = stringStream.toArray(size -> new String[size]);
Arrays.stream(stringArray).forEach(System.out::println);

Impressões:

a
b
c

8
e aqui está uma explicação por que e como a referência construtor Array realmente trabalho: stackoverflow.com/questions/29447561/...
jarek.jpa

"O Zenexer está certo, a solução deve ser: stream.toArray (String [] :: new);" ... Bem, ok, mas é preciso entender que a referência do método é lógica e funcionalmente equivalente a toArray(sz -> new String[sz])isso, então não tenho certeza de que se possa realmente dizer qual deve ou deve ser a solução.
scottb

3
@scottb cria sz -> new String[sz]uma nova função onde, como a referência do construtor, não. Depende de quanto você valoriza a Garbage Collection Churn, eu acho.
WORMSS 18/08/19

3
@WORMSS Isso não acontece. Ele (estaticamente!) Cria um private método novo, que não pode causar rotatividade, e as duas versões precisam criar um novo objeto. Uma referência cria um objeto que aponta diretamente para o método de destino; um lambda cria um objeto que aponta para o gerado private. Uma referência a um construtor ainda deve ter um desempenho melhor por falta de indireção e otimização mais fácil da VM, mas a agitação não tem nada a ver com isso.
HTNW

2
@HTNW você está correto, peço desculpas. De fato, foi minha tentativa de depurar que estava causando a rotatividade na primeira vez que tentei fazer isso, por isso fiquei presa na cabeça que era assim. (Odeio quando isso acontece).
WORMSS

41

Se você deseja obter uma matriz de entradas, com valores de 1 a 10, de um Stream, há o IntStream à sua disposição.

Aqui, criamos um Stream com o método Stream.of e convertemos um Stream em um IntStream usando um mapToInt. Em seguida, podemos chamar o método toArray do IntStream.

Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9,10);
//or use this to create our stream 
//Stream<Integer> stream = IntStream.rangeClosed(1, 10).boxed();
int[] array =  stream.mapToInt(x -> x).toArray();

Aqui está a mesma coisa, sem o Stream, usando apenas o IntStream

int[]array2 =  IntStream.rangeClosed(1, 10).toArray();

16

Você pode converter um fluxo java 8 em uma matriz usando este bloco de código simples:

 String[] myNewArray3 = myNewStream.toArray(String[]::new);

Mas vamos explicar mais, primeiro, vamos criar uma lista de strings preenchidas com três valores:

String[] stringList = {"Bachiri","Taoufiq","Abderrahman"};

Crie um fluxo a partir da matriz fornecida:

Stream<String> stringStream = Arrays.stream(stringList);

agora podemos executar algumas operações nesse fluxo Ex:

Stream<String> myNewStream = stringStream.map(s -> s.toUpperCase());

e, finalmente, converta-o em uma matriz java 8 usando estes métodos:

Método 1-Classic (interface funcional)

IntFunction<String[]> intFunction = new IntFunction<String[]>() {
    @Override
    public String[] apply(int value) {
        return new String[value];
    }
};


String[] myNewArray = myNewStream.toArray(intFunction);

Expressão 2 -ambda

 String[] myNewArray2 = myNewStream.toArray(value -> new String[value]);

3- Referência do método

String[] myNewArray3 = myNewStream.toArray(String[]::new);

Referência de método Explicação:

É outra maneira de escrever uma expressão lambda que é estritamente equivalente à outra.


7

Converta o texto na matriz de cadeias onde separa cada valor por vírgula e apara todos os campos, por exemplo:

String[] stringArray = Arrays.stream(line.split(",")).map(String::trim).toArray(String[]::new);

5

Você pode criar um coletor personalizado que converte um fluxo em matriz.

public static <T> Collector<T, ?, T[]> toArray( IntFunction<T[]> converter )
{
    return Collectors.collectingAndThen( 
                  Collectors.toList(), 
                  list ->list.toArray( converter.apply( list.size() ) ) );
}

e um uso rápido

List<String> input = Arrays.asList( ..... );

String[] result = input.stream().
         .collect( CustomCollectors.**toArray**( String[]::new ) );

5
Por que você usaria isso em vez de Stream.toArray (IntFunction) ?
Didier L

Eu precisava de um coletor para passar para o 2-arg, Collectors.groupingBypara que eu pudesse mapear algum atributo para matrizes de objetos por valor de atributo. Essa resposta me dá exatamente isso. Também @DidierL.
Ole VV

3

Usar o toArray(IntFunction<A[]> generator)método é realmente uma maneira muito elegante e segura de converter (ou mais corretamente, coletar) um fluxo em uma matriz do mesmo tipo do fluxo.

No entanto, se o tipo da matriz retornada não for importante, o simples uso do toArray()método será mais fácil e mais curto. Por exemplo:

    Stream<Object> args = Stream.of(BigDecimal.ONE, "Two", 3);
    System.out.printf("%s, %s, %s!", args.toArray());

0
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

int[] arr=   stream.mapToInt(x->x.intValue()).toArray();

0
import java.util.List;
import java.util.stream.Stream;

class Main {

    public static void main(String[] args) {
        // Create a stream of strings from list of strings
        Stream<String> myStreamOfStrings = List.of("lala", "foo", "bar").stream();

        // Convert stream to array by using toArray method
        String[] myArrayOfStrings = myStreamOfStrings.toArray(String[]::new);

        // Print results
        for (String string : myArrayOfStrings) {
            System.out.println(string);
        }
    }
}

Experimente online: https://repl.it/@SmaMa/Stream-to-array


Qual é a diferença entre sua resposta e a resposta aceita?
Long Nguyen

@LongNguyen É um exemplo completo, incluindo um cenário de repetição online, não apenas um trecho.
Sma Ma 06/04

-1
     Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

     Integer[] integers = stream.toArray(it->new Integer[it]);

-2

Você pode fazê-lo de várias maneiras. Todas as formas são tecnicamente iguais, mas o uso do Lambda simplificaria parte do código. Digamos que inicializamos uma Lista primeiro com String, chame-a de pessoas.

List<String> persons = new ArrayList<String>(){{add("a"); add("b"); add("c");}};
Stream<String> stream = persons.stream();

Agora você pode usar uma das seguintes maneiras.

  1. Usando a expressão Lambda para criar um novo StringArray com tamanho definido.

    String [] stringArray = stream.toArray (tamanho-> novo String [tamanho]);

  2. Usando a referência do método diretamente.

    String [] stringArray = stream.toArray (String [] :: new);

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.