8
votes

I have a custom class Custom.

public class Custom {

  private Long id;

  List<Long> ids;

  // getters and setters
}

Now I have List<Custom> objects. I want to convert List<Custom> into List<Long>. I have written the code as below and it is working fine.

    List<Custom> customs = Collections.emptyList();
    Stream<Long> streamL = customs.stream().flatMap(x -> x.getIds().stream());
    List<Long> customIds2 = streamL.collect(Collectors.toList());
    Set<Long> customIds3 = streamL.collect(Collectors.toSet());

Now I'm combining the line2 and line3 into single line as below.

    List<Long> customIds = customs.stream().flatMap(x -> x.getIds().stream()).collect(Collectors.toSet());

Now, this code is not compiling and I'm getting below error -

    error: incompatible types: inference variable R has incompatible bounds
            List<Long> customIds = customs.stream().flatMap(x -> x.getIds().stream()).collect(Collectors.toSet());
                                                                                            ^
        equality constraints: Set<Long>
        upper bounds: List<Long>,Object
    where R,A,T are type-variables:
        R extends Object declared in method <R,A>collect(Collector<? super T,A,R>)
        A extends Object declared in method <R,A>collect(Collector<? super T,A,R>)
        T extends Object declared in interface Stream

How can I convert the List<Custom> into Set<Long> or List<Long> correctly

2
Collectors.toSet(), as its name indicates, creates a Set. Not a List. So you can't assign the result to List<Long> customIds. - JB Nizet
The original code would never work, because you can only call collect() once on streamL. The second call throws IllegalStateException: stream has already been operated upon or closed - Andreas

2 Answers

5
votes

You can do it as :

List<Custom> customs = Collections.emptyList();
Set<Long> customIdSet = customs.stream()
                               .flatMap(x -> x.getIds().stream())
                               .collect(Collectors.toSet()); // toSet and not toList

The reason you get a compiler error is that you've used an incorrect Collector which returns a List instead of a Set which is your expected return type as you assign it to a variable of Set<Long> type.

4
votes

This should do the trick :

Set<Long> collectSet = customs.stream()
                           .flatMap(x -> x.getIds().stream())
                           .collect(Collectors.toSet());

You are trying to convert a Set to a List which is not possible.