Java 如何使用流有条件地终止集合上的循环

Java 如何使用流有条件地终止集合上的循环,java,java-8,java-stream,Java,Java 8,Java Stream,如何使用流来实现以下代码段所示的功能? 基本上,我需要终止一个循环,根据一个条件返回一个值,或者根据一个条件再次返回另一个值 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

如何使用流来实现以下代码段所示的功能? 基本上,我需要终止一个循环,根据一个条件返回一个值,或者根据一个条件再次返回另一个值

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;
}
枚举日{
星期日、星期一、星期二、星期三
} 
MyObj类{
d天;
公众日;
}
列表列表;
Day Myfunc(){
//如果至少有一个obj属于星期日或星期一,请返回。
Day myDay=null;
for(MyObj MyObj:myObjList){
如果(myObj.getDay()==Day.SUNDAY | | myObj.getDay()==Day.MONDAY){
返回myObj.getDay();
}
else if(myObj.getDay()==Day.周二){
myDay=myObj.getDay();
}
}
返回myDay;
}

您可以像这样使用流:

list.stream().filter(myObj -> myObj.getDay() == Day.SUNDAY || myObj.getDay() == Day.MONDAY);

对于终止
返回
它本身可以终止循环。

我理解您函数的逻辑如下:

  • 如果输入中有星期天或星期一,则返回其中的第一个
  • 否则如果是星期二,就把它退回
  • 否则返回null
  • 您可以用Java-8样式实现此逻辑,迭代列表两次并使用
    可选。OrelGet

    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);
    
    看起来有点难看,所以最好还是坚持原来的命令式代码


    另一种一次性解决方案是引入天数优先级并使用它:

    int priority(Day d) {
        switch(d) {
        case SUNDAY:
        case MONDAY:
            return 10; // max priority
        case TUESDAY:
            return 5;
        default:
            return 0;
        }
    }
    
    现在您可以使用
    Stream.max

    return myObjList.stream().map(MyObj::getDay).max(Comparator.comparingInt(this::priority))
            .filter(day -> priority(day) > 0).orElse(null);
    

    虽然它比原始代码长,但这种解决方案看起来更灵活:通过调整
    优先级
    方法,您可以轻松添加更多案例。

    您可以使用brake停止循环条件。但是,如果周日或周一,我需要以一种方式终止循环,如果周二,则以另一种方式终止循环。因此,我正在寻找一些使用流的if-else-if逻辑。然后您已经添加了单词
    return
    它可以终止循环,无需为此执行额外的代码。好的,我正在寻找类似“orElseGet()”的东西。谢谢正如你所说,我也认为原始代码看起来更干净。但是OP希望最后一次出现的
    Tusesday
    的详细信息不是第一次出现的,我想
    anyMatch()
    会给你第一次出现的
    Tusesday
    的详细信息,如果我们想使用流,我想我们必须迭代列表两次。相反,使用旧样式的for循环更有效。@singhakash,它是枚举,因此最后一个星期二与第一个星期二无法区分。@singhakash,代码返回的不是原始列表元素(属于
    MyObj
    type),而是
    Day
    enum值。再看一遍。