I am staring at some imperative code which I am trying to convert to a purely functional style.
Basically there is a iterative for-loop over inputSet
in which
Another approach would be to use the Consumer.andThen(anotherConsumer) method to create a composed consumer made of inner consumers that execute in sequence. Each one of these inner consumers would test every predicate and classify elements depending on whether they match or not.
public static Consumer classify(Predicate predicate, Consumer action) {
return elem -> Optional.ofNullable(elem)
.filter(predicate)
.ifPresent(action);
}
This utility method returns a consumer that will execute the given action on the element being consumed, as long as the predicate returns true
for the element.
Test:
Stream stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
Set set1 = new LinkedHashSet<>();
Set set2 = new LinkedHashSet<>();
Set set3 = new LinkedHashSet<>();
// Here's the composed consumer, made of inner consumers
Consumer multiClassifier = classify(n -> n % 2 == 0, set1::add)
.andThen(classify(n -> n % 3 == 0, set2::add))
.andThen(classify(n -> n % 5 == 0, set3::add));
// Here the stream is consumed by the composed consumer
stream.forEach(multiClassifier);
Each inner consumer is created with the utility method defined above, which receives an independent predicate that, when matched, will add the element of the stream to the given set, i.e. if the element of the stream is a multiple of 3, it will be added to set2
.
At the end, the stream is consumed with this composed consumer and thus the stream is classified by independent predicates:
System.out.println(set1); // [2, 4, 6, 8, 10, 12]
System.out.println(set2); // [3, 6, 9, 12]
System.out.println(set3); // [5, 10]