2017-06-22 110 views
3

后抛出异常,我有这样的代码:需要继续过滤Java流时,图过滤和使用FindFirst

return myList 
    .stream() 
    .filter(Objects::nonNull) 
    .filter(listItem -> { 
     try { 
      return listItem.matchesCondition(); 
     } catch (Exception e) { 
      // log error 
      return false; 
     } 
    }) 
    .findFirst() 
    .map(listItem -> { 
     try { 
      return listItem.getResult(); 
     } catch (Exception e) { 

      // IF THIS HAPPENS, HOW CAN WE ADVANCE TO THE NEXT ITEM IN THE STREAM. 
      // I'M ASSUMING WE CAN NOT SINCE THE STREAM WAS TERMINATED BY findFirst. 
      // BUT HOW CAN I WRITE THIS IN A DIFFERENT WAY TO ACHIEVE THAT BEHAVIOR? 

      // log error 
      return null; 
     } 
    }); 

的问题是,如果第一个匹配的listItem全中,地图功能异常,空可选的是回。

但相反,我想继续测试列表中的其余项目,并尝试映射与过滤器匹配的下一个项目。

我该如何做到这一点与流和lambdas?

我可以转换为这个更强制性的代码,但希望找到一个功能性的解决方案。

for (MyListItem myList : listItem) { 
    try { 
     if (listItem.matchesCondition()) { 
      return Optional.of(listItem.getResult()); 
     } 
    } catch (Exception e) { 

     // SWALLOW THE EXCEPTION SO THE NEXT ITEM IS TESTED 

     // log error 
    } 
} 

return Optional.empty(); 

回答

3

你必须在findFirst移动到尽头,因为它降低了流只(最多)一个元素,你不能“回去”,并得到后多。

return myList 
    .stream() 
    .filter(Objects::nonNull) 
    .filter(...) 
    .map(...) // returns null on Exception, so filter again 
    .filter(Objects::nonNull) 
    .findFirst() 
+1

另一方面,不是'.MAP(为空的除外).filter(对象::非空)'你可以使用'.flatMap(的listItem - > {{尝试返回Stream.of(listItem.getResult( ));} catch(Exception e){return null;}})'。 'flatMap'操作将像'Stream.empty()'一样对待'null'。 – Holger

+0

@Holger。我想过(或Option.of上类似的flatMap)。但它与筛选器(:: nonNull)一样嘈杂。很高兴有像Scala的'.flatMap(Try(....)。toOption)'这样的东西来忽略流中的异常。 – Thilo

+1

那么,你可以做一个实用的方法做到这一点。 – Holger