【问题标题】:JAVA 8 : Change value inside streamJAVA 8:更改流内的值
【发布时间】:2019-01-31 16:10:47
【问题描述】:

我有一个对象列表,我在这个列表的每个元素上循环并修改了几个属性。

这是我想要转换以使用流 API 的代码。

        for (Besoin besoin : besoins) {
        String purchaseOrderPosition = besoin.getReferenceOa().trim();
        if(purchaseOrderPosition != "") {
            ValeursDynamiques valeursDynamiques = valeursDynamiquesService.DynamicValues(supplierNumber, purchaseOrderPosition);
            besoin.setQuantityInTransit(valeursDynamiques.getUsedValues().getQteEnTransit());
            besoin.setQuantityOrdered(valeursDynamiques.getUsedValues().getQteCommandee());
            besoin.setQuantityDelivered(valeursDynamiques.getUsedValues().getQteRecue());
            besoin.setDeliveryDateScheduled(valeursDynamiques.getUsedValues().getDateLivraisonPlanifiee());
            besoin.setDeliverydateConfirmed(valeursDynamiques.getUsedValues().getDateLivraisonConfirmee());
            besoin.setQuantityRestExpedited(valeursDynamiques.getUsedValues().getSoldeAExpedier());
        }   
    }

【问题讨论】:

  • 为什么还需要将此代码转换为流?我认为这不会有任何好处。
  • 你的意思是something like this,注意字符串应该用.equals而不是==比较
  • 我认为,如果您必须对一个实例执行这么多操作,那么流的可读性就会降低。此外,流不能/不应该改变源,因此在这种情况下,您必须创建一个新列表。查看@YCF_L 的代码,您最终会得到列表的副本,但仅包含过滤后的元素。因此,如果您确实需要所有这些,或者需要改变源,我会坚持使用经典循环。
  • @YCF_L 感谢您的回答,但 .equals (...) 和 isEmpty 有什么区别?

标签: java list foreach java-stream


【解决方案1】:

这应该是正确的,因为您不是在修改列表而是在修改元素的属性:

    besoins.stream().forEach(besoin -> {
    String purchaseOrderPosition = besoin.getReferenceOa().trim();
    if(!purchaseOrderPosition.isEmpty()) {
        ValeursDynamiques valeursDynamiques = valeursDynamiquesService.DynamicValues(supplierNumber, purchaseOrderPosition);
        besoin.setQuantityInTransit(valeursDynamiques.getUsedValues().getQteEnTransit());
        besoin.setQuantityOrdered(valeursDynamiques.getUsedValues().getQteCommandee());
        besoin.setQuantityDelivered(valeursDynamiques.getUsedValues().getQteRecue());
        besoin.setDeliveryDateScheduled(valeursDynamiques.getUsedValues().getDateLivraisonPlanifiee());
        besoin.setDeliverydateConfirmed(valeursDynamiques.getUsedValues().getDateLivraisonConfirmee());
        besoin.setQuantityRestExpedited(valeursDynamiques.getUsedValues().getSoldeAExpedier());
    }   
}

你可以直接使用列表中的forEach(),我使用isEmpty() intead of != ""

但如前所述,为什么在这里使用 Stream ? besoins.stream().forEach(besoin -> 的可读性不如 for (Besoin besoin : besoins)

一般来说,当更喜欢流来过滤、映射和提取一些数据时

【讨论】:

  • 但是当我们可以使用流时,为什么要使用它?对我来说,我想使用 Stream,因为我在项目中使用 Java 8。
  • 是的,可以很好地使用流,就像我的回答一样。但是 foreach 循环更易于阅读,通常使用列表上的流来应用过滤器或映射,然后提取其他列表或其他东西......
  • @user43968 好笑 :) 你在 1/2 小时后写了答案,上面写着正是我做了什么......
  • @Eugene 我看不到您在答案中使用 Stream 的位置以及转换 for 循环的位置;),而对于另一部分,我说“如前所述”
  • 这是循环和流之间的奇怪组合。假设 boseins 是一个集合,即使 besoins.forEach(...) 也可以。我还建议将消费者提取到可测试性方法:besoins.forEach(this::foo) 和:void foo(final Besoins value) { ... }
【解决方案2】:

修改流的中的元素不是源本身的结构变化。是的,你可以做到,即使在parallel 这也不会失败。但这并不是重点。除非您有其他可能需要的操作(filtermap 等),否则您的循环会更有意义。

例如ArrayList 文档说:

...仅仅设置一个元素的值不是结构修改

因此,您修改元素但不修改流源的代码(在您的情况下为List)将不会抛出ConcurrentModificationException

【讨论】:

  • 但在我的情况下,更改发生在源(列表)流中,它只是一个数据管道
  • @CHARAFISaad 对不起,我不明白你在说什么
  • Stream 以 Collection 或 Array 的形式从源提供数据,并且不修改源。在过滤器和修改后,我们使用 collect() 方法转换为新列表
  • @CHARAFISaad 好的......你的问题是?我又不明白你了。关键是如果您修改 List - 那是您的流的 ,例如添加或删除列表中的元素 - 这是一个结构更改,这将不起作用 (ConcurrentModificationException) ;如果您修改了该列表中不是结构更改的元素之一的属性并且您的代码很好。
猜你喜欢
  • 2015-09-16
  • 1970-01-01
  • 2019-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-24
相关资源
最近更新 更多