Home > Blockchain >  Correct way to apply different fucntions based on condition in stream
Correct way to apply different fucntions based on condition in stream

Time:03-02

What would be the correct way to implement this functional logic with streams?

  1. Stream through list of items

  2. Check if condition 1 passes, if so apply function 1 to the item.

    Check if condition 2 passes, if so apply function 2 to the item.

    If both conditions do not pass, do nothing.

  3. collect results

Do I create predicates with suppliers or how does this look? I'm not very familiar with functional Java.

CodePudding user response:

You're probably best off with a simple for loop, but you could do:

List<Item> list;
list.stream()
    .forEach(item -> {
       boolean condition1 = predicate1.test(item);
       boolean condition2 = predicate2.test(item);
       if(condition1 && !condition2) {
            applyFunction1(item);
       } else if(!condition1 && condition2) {
            applyfunction2(item);
       }
   });

This operates directly on the underlying list. Use map if you want to collect to a different collection (but obviously it depends on the modifying function implementation whether it contains clones or the original, now also modified, objects):

List<Item> list;
List<Item> modifiedList = list.stream()
   .map(item -> {
       if(condition1 && !condition2) {
            return function1.apply(item);
       } else if(!condition1 && condition2) {
            return function2.apply(item);
       }
       return item;
   })
   .toList();

If you do not care about the final ordering of items, here's another approach, which you can see gets silly...:

    List<Item> list;
    Predicate<Item> predicate1;
    Predicate<Item> predicate2;
    Function<Item, Item> function1;
    Function<Item, Item> function2;

    Stream<Item> modifiedBy1 = list.stream()
        .filter(predicate1.and(predicate2.negate()))
        .map(function1);
    Stream<Item> modifiedBy2 = list.stream()
        .filter(predicate1.negate().and(predicate2))
        .map(function1);
    Stream<Item> unmodified = list.stream()
        .filter(predicate1.negate().and(predicate2.negate()));
    
    Stream<Item> recombined = Stream
        .of(modifiedBy1, modifiedBy2, unmodified) //a Stream of Streams
        //you can influence the order of elements by swapping these around
        //the result is essentially sorted by which conditions where matched
        .flatMap(Function.identity()); //flatten the streams back to their constituent objects
    //could also have used 2x Stream.concat here
  • Related