879

What is the easiest/shortest way to convert a Java 8 Stream into an array?

MC Emperor
  • 17,266
  • 13
  • 70
  • 106
  • 2
    I'd suggest you to revert the rollback as the question was more complete and showed you had tried something. – skiwi Apr 15 '14 at 09:13
  • 2
    @skiwi Thanks! but i thought the attempted code does not really add more information to the question, and nobody has screamed "show us your attempt" yet =) –  Apr 15 '14 at 09:20
  • 18
    @skiwi: Although I usually shout at the do-my-homework-instead-of-me questions, this particular question seems to be clearer to me without any additional mess. Let's keep it tidy. – Honza Zidek Apr 16 '14 at 11:21
  • You can find a lot of answers and guidance in the official docs of the package: https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html – Christophe Roussy Apr 01 '20 at 09:07

11 Answers11

1329

The easiest method is to use the toArray(IntFunction<A[]> generator) method with an array constructor reference. This is suggested in the API documentation for the method.

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

What it does is find a method that takes in an integer (the size) as argument, and returns a String[], which is exactly what (one of the overloads of) new String[] does.

You could also write your own IntFunction:

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

The purpose of the IntFunction<A[]> generator is to convert an integer, the size of the array, to a new array.

Example code:

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

Prints:

a
b
c
Jens Bannmann
  • 4,355
  • 5
  • 45
  • 73
skiwi
  • 59,273
  • 29
  • 118
  • 198
  • 9
    and here is an explanation why and how the Array constructor reference actually work: http://stackoverflow.com/questions/29447561/how-do-java-8-array-constructor-references-work – jarek.jpa Sep 12 '16 at 18:16
  • 2
    *"Zenexer is right, the solution should be: stream.toArray(String[]::new);"* ... Well ok, but one should understand that the method reference is logically and functionally equivalent to `toArray(sz -> new String[sz])` so I'm not sure that one can really say what the solution should or must be. – scottb Apr 20 '17 at 14:16
  • The array constructor reference is more concise. The documentation for the `toArray()` method cites its concision and includes its use in the only example. When it was tacked on the end of the answer, I missed it on first reading. Moved it to the top, above the details, so that no one else will miss it. – Andy Thomas May 01 '17 at 19:44
  • 3
    @scottb `sz -> new String[sz]` makes a new function where as the constructor reference does not. It depends how much you value Garbage Collection Churn I guess. – WORMSS Aug 18 '17 at 09:19
  • 6
    @WORMSS It does not. It (statically!) makes a new, `private` *method*, which cannot cause churn, and *both* versions need to create a new object. A reference creates an object that points directly at the target method; a lambda creates an object that points at the generated `private` one. A reference to a constructor should still perform better for lack of indirection and easier VM optimization, but churning has nothing to do with it. – HTNW Oct 29 '17 at 23:54
  • 2
    @HTNW you are correct, my apologise. It was infact my attempt to debug that was causing the churn that was causing the churn the first time I tried to do this, so I have had it stuck in my head that this is how it was. (Hate it when that happens). – WORMSS Oct 30 '17 at 08:38
  • "String[] stringArray = stringStream.toArray(size -> new String[size]);", where is the size come from? – user1169587 Jan 06 '21 at 07:25
  • Lambda should simplify things but java lambda like `stream.toArray(size -> new String[size]);` just looks akward and this is so unintuitive every developer will forget this syntax the next time he needs an array. Why do they make things so complicated where c# is making life pretty easy with lambda. My stack is java but since years java getting more and more behind of c#. – djmj Mar 22 '21 at 02:09
46

If you want to get an array of ints, with values from 1 to 10, from a Stream<Integer>, there is IntStream at your disposal.

Here we create a Stream with a Stream.of method and convert a Stream<Integer> to an IntStream using a mapToInt. Then we can call IntStream's toArray method.

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();

Here is the same thing, without the Stream<Integer>, using only the IntStream:

int[]array2 =  IntStream.rangeClosed(1, 10).toArray();
S.S. Anne
  • 13,819
  • 7
  • 31
  • 62
Ida Bucić
  • 711
  • 6
  • 10
25

You can convert a java 8 stream to an array using this simple code block:

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

But let's explain things more, first, let's Create a list of string filled with three values:

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

Create a stream from the given Array :

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

we can now perform some operations on this stream Ex:

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

and finally convert it to a java 8 Array using these methods:

1-Classic method (Functional interface)

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


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

2 -Lambda expression

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

3- Method reference

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

Method reference Explanation:

It's another way of writing a lambda expression that it's strictly equivalent to the other.

9

Convert text to string array where separating each value by comma, and trim every field, for example:

String[] stringArray = Arrays.stream(line.split(",")).map(String::trim).toArray(String[]::new);
Lee Mac
  • 14,469
  • 6
  • 23
  • 70
5

You can create a custom collector that convert a stream to array.

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

and a quick use

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

String[] result = input.stream().
         .collect( CustomCollectors.**toArray**( String[]::new ) );
  • 5
    Why would you use this instead of [Stream.toArray(IntFunction)](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#toArray-java.util.function.IntFunction-)? – Didier L May 31 '18 at 12:41
  • I needed a collector to pass to the 2-arg `Collectors.groupingBy` so that I could map some attribute to arrays of objects per attribute value. This answer gives me exactly that. Also @DidierL. – Ole V.V. Dec 09 '18 at 13:34
  • Since Java 11 the _finisher_ in _collectingAndThen_ can be written as `list -> list.toArray(converter)` due to addition of [Collection.toArray​(IntFunction)](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Collection.html#toArray(java.util.function.IntFunction)) – bjmi Nov 22 '20 at 09:45
3

Using the toArray(IntFunction<A[]> generator) method is indeed a very elegant and safe way to convert (or more correctly, collect) a Stream into an array of the same type of the Stream.

However, if the returned array's type is not important, simply using the toArray() method is both easier and shorter. For example:

    Stream<Object> args = Stream.of(BigDecimal.ONE, "Two", 3);
    System.out.printf("%s, %s, %s!", args.toArray());
Kunda
  • 391
  • 1
  • 5
1
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

int[] arr=   stream.mapToInt(x->x.intValue()).toArray();
Raj N
  • 219
  • 1
  • 13
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);
        }
    }
}

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

Sma Ma
  • 1,729
  • 14
  • 29
-1
     Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

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

you can use the collector like this

  Stream<String> io = Stream.of("foo" , "lan" , "mql");
  io.collect(Collectors.toCollection(ArrayList<String>::new));
said
  • 17
  • 3
-2

You can do it in a few ways.All the ways are technically the same but using Lambda would simplify some of the code. Lets say we initialize a List first with String, call it persons.

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

Now you can use either of the following ways.

  1. Using the Lambda Expresiion to create a new StringArray with defined size.

    String[] stringArray = stream.toArray(size->new String[size]);

  2. Using the method reference directly.

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

raja emani
  • 107
  • 4