Skip to content
Advertisement

How to divide a stream by object fields into two sets?

I have a stream, where each object is identified by a unique id. Moreover, each object has a either positive or negative Free values.

I want to divide this stream into two Sets, where one contains the ids whose Free values was positive, and one with the rest.

But I find the following not being the right way, as I’m collecting into lists outside of the stream.

class Foo {
    int free;
    long id;
}

public Tuple2<Set<Long>, Set<Long>> findPositiveAndNegativeIds() {
    Set<Long> positives = new HashSet<>();
    Set<Long> negatives = new HashSet<>();

    foos.stream()
            .forEach(f -> {
                if (f.free >= 0) positigves.add(f.id);
                else negatives.add(f.id);
            });
            
    return Tuple2.tuple(positives, negatives);
}

Could this be done better, somehow with partitionBy() or similar?

Advertisement

Answer

You can indeed use partitioningBy. You can specify what to do with each partition in the second parameter.

var map = foos.stream().collect(Collectors.partitioningBy(
    foo -> foo.free >= 0, // assuming no 0
    // for each partition, map to id and collect to set
    Collectors.mapping(foo -> foo.id, Collectors.toSet())
));

map.get(true) will get you the set of ids with positive frees, and map.get(false) will get you the set of ids with negative frees.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement