【问题标题】:Java init object and set property using Stream使用 Stream 的 Java 初始化对象和设置属性
【发布时间】:2018-11-12 10:08:42
【问题描述】:

我正在尝试将列表克隆到新列表并在新列表中设置属性。 我正在尝试使用 Java8 Stream,因为它使克隆变得简单。 我的代码有效,但它使 Sonar 产生了这种代码气味:

不应声明局部变量然后立即返回或抛出(squid:S1488)

有没有办法在不使用局部变量的情况下做到这一点? 代码:

List<myObject> clonedList = listToClone.stream()
                                                .map(item ->  {
                                                    cloned = new myObject(item);
                                                    cloned.setLifeCycle("someLifeCycle");
                                                    return cloned;
                                                })
                                                .collect(Collectors.toList());

谢谢

【问题讨论】:

  • 你能用完整的代码和错误编辑你的问题吗?
  • 我不确定您的问题出在 map 方法上。你能展示剩下的方法吗?我对您的 map 方法的问题是该变量未在 map 方法中声明。我总是使用尽可能小的范围。但这不是你的问题
  • @Sodala 另一方面,如果 cloned 不是局部变量,则不会编译。奇怪。
  • 请阅读“如何创建minimal reproducible example”。然后使用edit 链接改进您的问题(不要通过 cmets 添加更多信息)。否则我们无法回答您的问题并为您提供帮助。
  • 这个答案是指过滤器但基本相同:stackoverflow.com/a/45793560/9354242

标签: java dictionary java-stream


【解决方案1】:

这是一个警告,因为您不必要地使用了新变量 cloned,而不是直接链接函数,如

List<myObject> clonedList = listToClone.stream()
    .map(item -> {return (new myObject(item)).setLifeCycle("someLifeCycle");})
    .collect(Collectors.toList());

【讨论】:

  • 或者只是 .map(item -&gt; new myObject(item).setLifeCycle("someLifeCycle")) 假设 setLifeCycle 不返回 void
【解决方案2】:

你可以试试这个:

List<myObject> clonedList = listToClone.stream()
                                       .map(myObject::new)
                                       .map(o -> {
                                           o.setLifeCycle("someLifeCycle");
                                           return o;
                                       })
                                       .collect(Collectors.toList());

【讨论】:

  • 我不会忽略要映射的函数应该是“应用于每个元素的无状态函数”这一事实。
  • @Aomine 好吧,收集新对象然后在 clonedList 上调用forEach 设置我们需要的属性会更干净。问题是我们是否可以在没有局部变量的情况下做到这一点
  • “问题是我们是否可以在没有局部变量的情况下做到这一点”。因此,listToClone.stream() .map(myObject::new).peek(o -&gt; o.setLifeCycle("someLifeCycle")).collect(toList()) 不是 整洁 吗?其中“是”与有状态的 map 函数一样糟糕,因为 peek 应该仅用于调试目的。无论如何,如果您要建议此代码,那么至少说明它可能导致的问题。与您的解决方案不同,OP 显示的原始代码将按顺序和并行完美运行。
  • 不要因为这样的原因使用 peek,它应该只用于调试,因此 java 文档告诉我们:docs.oracle.com/javase/8/docs/api/java/util/stream/…
  • @Aomine 为什么并行工作不安全?无论如何,初始列表中每个项目的映射都将按顺序执行。
【解决方案3】:
        public class MyObject{
         private String someLifeCycle;
         private Item item;
          public MyObject(final String someLifeCycle,final Item item){
            this.someLifeCycle = someLifeCycle;
            this.item = item;
           }
          //getters and setters
        }

你的代码会是这样的:

    List<MyObject> clonedList = listToClone.stream()
 .map(item -> new MyObject(item,"someLifeCycle")).collect(Collectors.toList());

【讨论】:

  • 我会给 UnaryOperator 的东西 +1,我还没有看到。但是然后 -1 只是删除了一堆(缩进不是很好)代码。所以,零和游戏。
  • @GhostCat 甚至无法编译。
  • @Aomine 什么不能编译?
  • @MykhailoMoskura final someLifeCycle
  • 对不起,这是我打字快的错字
猜你喜欢
  • 1970-01-01
  • 2013-02-24
  • 2012-12-15
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-12
  • 1970-01-01
相关资源
最近更新 更多