使用Java流式API从list.forEach返回列表

使用Java流式API从list.forEach返回列表,java,java-stream,Java,Java Stream,我有一个POJO: class MyObject { private Double a; private String b; //constructor, getter + setter } 某些函数正在创建此POJO的列表。a的某些值可能为空,因此我想将它们替换为0.0。目前我正在这样做 public List<MyObject> fetchMyObjects(Predicate predicate) { List<MyObject>

我有一个POJO:

class MyObject {
   private Double a;
   private String b;

   //constructor, getter + setter
}
某些函数正在创建此POJO的列表。
a
的某些值可能为空,因此我想将它们替换为0.0。目前我正在这样做

public List<MyObject> fetchMyObjects(Predicate predicate) {

     List<MyObject> list = getMyListsOfTheDatabase(predicate);

     list
       .forEach(myObject -> {
           if (myObject.getA() == null) {
               myObject.setA(0.0);
           }
     });

    return list;
}

这不是关于将空值转换为零的最佳位置,而是关于如何更好地理解流式api的问题。

forEach
没有返回值,因此您可能要查找的是
map

return list
    .stream()
    .map(e -> {
        if (e.getA() == null) e.setA(0d);
        return e;
    })
    .whateverElse()...

不能使用单个语句返回相同的
List
实例,但可以返回包含相同(可能已修改)元素的新
List
实例:

return list.stream()
           .map(myObject -> {
               if (myObject.getA() == null) {
                   myObject.setA(0.0);
               }
               return myObject;
           })
           .collect(Collectors.toList());
使用函数

返回一个由该流的元素组成的流,在从结果流中消耗元素时,对每个元素执行提供的操作

public List fetchMyObjects(谓词){
返回getMyListsOfTheDatabase(谓词)
.stream()
.peek(it->if(it.getA()==null)it.setA(0.0))
.collect(Collectors.toList());
}

实际上,您应该使用
List::replaceAll

list.replaceAll(x -> {
    if(x.getA() == null) x.setA(0.0D);
    return x;
})

以下情况可以:

list.stream()
    .filter(obj -> obj.getA() == null)
    .forEach(obj -> obj.setA(0.0));
return list;
但是,在您的情况下,仅返回流可能更合适(取决于):

公共流fetchMyObjects(谓词){
返回getMyListsOfTheDatabase(谓词);
}
公共流StreamMyObject(列表){
return list.stream()
.peek(对象->{
if(obj.getA()==null){
目标毛(0.0);
}
});
}
我个人从未使用过
peek
,但在这里它修正了值

关于代码约定,在java社区中它们更像字符串:

  • 缩进:Java将4作为更独立的方法,而不是C++的3, 预计压痕会减少。有争议但没问题
  • 对于泛型类型参数,通常使用单个大写字母,如
    T、C、S
  • 对于lambda参数,短名称通常是一个字母,因此我使用了
    obj

    • 当其他人很乐意回答你的问题时,请允许我退一步,给你你没有要求的答案(但可能是你想要的答案):你不想这样做。流操作应该没有副作用。您所要求的正是一个流操作,它的副作用是修改进入流中的原始对象。这是一种糟糕的代码风格,可能会让那些在您之后阅读您的代码的人感到困惑

      您已经拥有的代码比任何组合流管道都能更好地解决您的问题

      如果您可以修改POJO,您可能需要的是,如果从数据库中检索到
      null
      ,则将
      a
      设置为0的构造函数,或者可以从
      列表调用的方法。forEach

          list.forEach(MyObject::setAToZeroIfNull);
      
      这不是关于,如果这是将空值转换为空值的最佳位置 零,而是一个更好地理解流式api的问题


      这很公平。在任何情况下,我都会让这个答案代表任何其他突然出现的人。

      list.forEach()
      相比,它有什么优势?(在我看来,这只是更加冗长/可读性较差。)@OleV.V。我想你是对的,这只是我的习惯。这是一个非常非常糟糕的建议<在这种情况下,可能根本不执行code>peek,因为不需要它。您能解释一下原因吗?在java-9中运行
      Stream.of(1,2,3,4).map(x->{System.out.println(x);返回x+1;}).count()
      。同样的道理,在这个流中,您所关心的只是一个基于
      getMyListsOfTheDatabase
      计算的列表;但是您没有以任何形式更改输入,因此
      peek
      可能会被完全丢弃。谢谢您的帖子,非常感谢。谢谢,效果很好。但是作为@OleV.V。写下,一个人不应该这样做:)
      public Stream<MyObject> fetchMyObjects(Predicate predicate) {
           return getMyListsOfTheDatabase(predicate);
      }
      
      public Stream<MyObject> streamMyObjects(List<MyObject> list) {
           return list.stream()
               .peek(obj -> {
                   if (obj.getA() == null) {
                       obj.setA(0.0);
                   }
               });
      }
      
          list.forEach(MyObject::setAToZeroIfNull);