Vasco
Vasco

Reputation: 802

Java Stream Collectors.toList() wont compile

Can any one explain why the below code will not compile but the second one does?

Do not compile

private void doNotCompile() {

    List<Integer> out;
    out = IntStream
            .range(1, 10)
            .filter(e -> e % 2 == 0)
            .map(e -> Integer.valueOf(2 * e))
            .collect(Collectors.toList());

    System.out.println(out);
}

Compilation errors on the collect line

Compiles

private void compiles() {
    List<Integer> in;

    in = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
    List<Integer> out;
    out = in.stream()
            .filter(e -> e % 2 == 0)
            .map(e -> 2 * e)
            .collect(Collectors.toList());

    System.out.println(out);
}

Upvotes: 3

Views: 3750

Answers (3)

Eran
Eran

Reputation: 393771

IntStream doesn't have a collect method that accepts a Collector. If you want a List<Integer>, you have to box the IntStream into a Stream<Integer>:

out = IntStream
        .range(1, 10)
        .filter(e -> e % 2 == 0)
        .map(e -> 2 * e)
        .boxed()
        .collect(Collectors.toList());

An alternative to .map().boxed() is mapToObj():

out = IntStream
        .range(1, 10)
        .filter(e -> e % 2 == 0)
        .mapToObj(e -> 2 * e)
        .collect(Collectors.toList ());

or you can use the IntStream collect method:

out = IntStream
        .range(1, 10)
        .filter(e -> e % 2 == 0)
        .map(e -> 2 * e)
        .collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll);

Upvotes: 12

Michael
Michael

Reputation: 44090

In the first example, you are operating over a stream of primitive integers. Primitive integers can't go into a List, basically because generics in Java are less than ideal. Java language designers are working on potentially fixing this.

In the meantime, to solve this you need to box these primitive ints into an Integer wrapper first. See Eran's answer for a code sample.

In the second example, you're already iterating over Integers so It Just Works™.


I thought I was boxing those int to Integers when I did Integer.valueOf in the mapper

The map function of IntStream takes a IntUnaryOperator which is a functional interface that takes a primitive int and returns a primitive int.

The Integer you get from valueOf is unboxed to match the functional interface.

Upvotes: 2

achAmh&#225;in
achAmh&#225;in

Reputation: 4266

The collect method of IntStream is different in the non-compilable case.

public <R> R collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R,R> combiner)

Therefore it does not accept the parameter you supplied to collect

You could get around this by casting List<Integer> to the IntStream

Upvotes: 1

Related Questions