【问题标题】:Java streams map with sideeffect and collect or foreach and populate a result-listJava 流映射具有副作用并收集或 foreach 并填充结果列表
【发布时间】:2017-08-14 14:01:52
【问题描述】:

我有一段看起来像这样的代码。

我已经阅读了关于此的两条相互矛盾的(?)“规则”。

我该如何解决这个问题,以便我使用流并仍然返回一个列表,还是应该直接跳过流?

@Transactional
public Collection<Thing> save(Collection<Thing> things) {
    return things.stream().map(this::save).collect(Collectors.toList());
}

@Transactional
public Thing save(Thing thing) {
    // org.springframework.data.repository.CrudRepository.save 
    // Saves a given entity. Use the returned instance for further operations as the save operation might have changed the entity instance completely.
    Thing saved = thingRepo.save(thing);
    return saved;
}

【问题讨论】:

  • 您能否提供有关 .foreach 规则的确切来源?它是关于它正在处理的对象的变量,还是任何类型的变量? (说“更新可变变量”有点奇怪——“更新不可变变量”是什么意思?)无论如何,我可能建议在这里使用 for 循环,通过显式集合管理,流并不能真正为您节省任何工作或在这里给出更清晰的说明。
  • 关键是要避免干扰。当同一个 Thing 实例在源集合中出现不止一次时,您可能会遇到它,但我假设您可以根据您的应用程序逻辑排除它。然后,这取决于thingRepo.save(…) 如何改变thingRepo 的状态。一般来说,在通过forEach 填充列表之前,我会考虑不使用流,因为后者不会产生比for 循环更简单、更清晰的代码。

标签: java foreach java-8 java-stream map-function


【解决方案1】:

那篇论文不是说 shared 可变状态吗?在您的情况下,如果您在方法中声明列表然后使用forEach,一切都很好。第二个答案here 准确地提到了您正在尝试做的事情。

【讨论】:

  • 是我的想法,但不确定他们所说的“共享”是什么意思,因为这个例子并不明显。如果可能的话,不确定你是否想要共享可变状态:) 第二个答案正是我所追求的(无顺序)
【解决方案2】:

如果你根本不改变它,几乎没有理由收集一个全新的List。除此之外,您的用例基本上是遍历集合中的每个元素并保存可以通过使用 for-each 简单实现的内容。

如果由于某种原因thingRepo.save(thing) 改变了对象,您仍然可以返回相同的集合,但此时它是一个隐藏的突变,根本看不到,因为thingRepo.save(thing) 不建议这样做。

【讨论】:

  • 保存是变异对象,保存给定的实体。使用返回的实例进行进一步的操作,因为保存操作可能已经完全改变了实体实例。
  • @ViktorMellgren 那么返回一个全新的集合就很好了。但这实际上取决于您是否真的需要拥有两个包含对象先前值和当前值的集合。
  • 我愿意 :) 需要设置的 id
猜你喜欢
  • 2017-09-22
  • 2015-07-27
  • 2019-04-08
  • 1970-01-01
  • 1970-01-01
  • 2017-07-26
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
相关资源
最近更新 更多