USE STREAMS FOR TERMINATING LOOP OVER COLLECTION CONDITIONALLY

marcel ethan

Total Post:105

Points:735
Posted by  marcel ethan
Java 
 438  View(s)
Ratings:
Rate this:
How to use streams to achieve something like what the following code snippet shows ? Basically, I need to terminate a loop returning one value based on a condition, or returning another value again, based on a condition.

enum Day {
  SUNDAY, MONDAY, TUESDAY, WEDNESDAY

class MyObj {
  Day d;
  public Day getDay();
}
List<MyObj> myObjList;
Day Myfunc () {
// If atleast one obj belongs to SUNDAY or MONDAY, return.
Day myDay = null;
for(MyObj myObj : myObjList) {
  if(myObj.getDay() == Day.SUNDAY || myObj.getDay() == Day.MONDAY) {
    return myObj.getDay();
  }
  else if (myObj.getDay() == Day.TUESDAY) {
    myDay = myObj.getDay();
  }
 }
return myDay;
}
  1. Mayank Tripathi

    Post:397

    Points:3117
    Re: Use streams for terminating loop over collection conditionally

    I understand the logic of your function as the following:

    If there's SUNDAY or MONDAY in the input, return the first one of them.
    Otherwise if there's TUESDAY, return it.
    Otherwise return null.
    You can implement this logic in the Java-8 style iterating the list twice and using Optional.orElseGet:

    myObjList.stream().map(MyObj::getDay).filter(d -> d == Day.SUNDAY || d == Day.MONDAY)
        .findFirst()
        .orElseGet(() -> myObjList
            .stream().map(MyObj::getDay).anyMatch(d -> d == Day.TUESDAY) ? Day.TUESDAY : null);
    Looks kinda ugly, so better to stick with the original imperative code.

    An alternative one-pass solution would be to introduce the days priority and use it:

    int priority(Day d) {
        switch(d) {
        case SUNDAY:
        case MONDAY:
            return 10; // max priority
        case TUESDAY:
            return 5;
        default:
            return 0;
        }
    }
    Now you can use Stream.max:

    return myObjList.stream().map(MyObj::getDay).max(Comparator.comparingInt(this::priority))
            .filter(day -> priority(day) > 0).orElse(null);
    Though it's longer than original code, such solution looks more flexible: you can easily add more cases tweaking the priority method.

Answer

NEWSLETTER

Enter your email address here always to be updated. We promise not to spam!