If I understand your intent correctly you want to filter out some values while collecting them. It's doable with Collectors.filtering().
Note, that filtering() can eliminate all values for some buckets, but it'll not cause empty buckets to be removed. In the example below buckets for 1, 2, 3, 4, 5 will be empty.
public static void main(String[] args) {
var foos = List.of(-100, 1, 2, 3, 4, 5, 1001, 1002, 1003);
var map = foos.stream()
.collect(Collectors.groupingBy(
UnaryOperator.identity(),
Collectors.filtering(foo -> foo < 0 || foo > 1000,
Collectors.toSet())));
System.out.println(map);
}
map
{1=[], 2=[], 3=[], -100=[-100], 4=[], 5=[], 1001=[1001], 1002=[1002], 1003=[1003]}
UPDATE
I revised this problem and the solution provided below computes the values beforehand.
In this version, undesired entries are filtered out in the stream, which makes the code inside Collector easier to read. I hope that instead of foo objects integer is used isn't a problem.
public static void main(String[] args) {
List<Integer> foos = List.of(-100, 1, 2, 3, 4, 5, 101, 102, 103);
Map<Integer, Integer> fooToValue = getFooToValueMap(foos);
Map<Boolean, Set<Integer>> map = getFoosMap(fooToValue);
System.out.println(map);
}
private static Map<Boolean, Set<Integer>> getFoosMap(Map<Integer, Integer> fooToValue) {
return fooToValue.entrySet().stream()
.filter(entry -> entry.getValue() < 0 || entry.getValue() > 1000)
.collect(Collectors.partitioningBy(
entry -> entry.getValue() > 1000,
Collectors.mapping(Map.Entry::getKey, Collectors.toSet())
));
}
private static Map<Integer, Integer> getFooToValueMap(List<Integer> list) {
return list.stream()
.collect(Collectors.toMap(UnaryOperator.identity(), foo -> complexEvaluation(foo)));
}
private static int complexEvaluation(int foo) {
return (int) Math.signum(foo) * foo * foo;
}
map
{false=[-100], true=[101, 102, 103]}