1

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?

membersound
  • 81,582
  • 193
  • 585
  • 1,120
  • Does this answer your question? [Java Stream: divide into two lists by boolean predicate](https://stackoverflow.com/questions/46958023/java-stream-divide-into-two-lists-by-boolean-predicate) – Didier L Feb 02 '22 at 14:21
  • Note that you can use [`partitioningBy(Predicate, Collector)`](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#partitioningBy-java.util.function.Predicate-java.util.stream.Collector-) in order to partition into sets instead of lists. – Didier L Feb 02 '22 at 14:22
  • 2
    Side note: conditional expressions work in this case too: `foos.forEach(f -> (f.free >= 0? positives: negatives).add(f.id));` – Holger Feb 02 '22 at 16:13

1 Answers1

6

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.

Sweeper
  • 213,210
  • 22
  • 193
  • 313