我正在使用Java-8修改一个对象
users.stream().filter(u -> u.count > 0).forEach(u -> u.setProperty("value"))
然而,我想要知道是否修改了任何对象......即,我需要一个布尔返回值,但是这个函数只返回空。
有什么办法可以实现吗?
如果我理解正确,您想知道在执行操作时是否有任何匹配项。您可以简单地使用两个语句。
boolean anyMatch = users.stream().anyMatch(u -> u.count > 0);
if(anyMatch) users.stream().filter(u -> u.count > 0).forEach(u -> u.setProperty("value"));
由于anyMatch
在第一次匹配到元素时就停止,所以只有在第一个匹配之前有大量不匹配的元素组成的长前缀时才会存在冗余工作。
如果这是一个问题,您可以使用
Spliterator<User> sp = users.stream().filter(u -> u.count > 0).spliterator();
boolean anyMatch = sp.tryAdvance(u -> u.setProperty("value"));
sp.forEachRemaining(u -> u.setProperty("value"));
替代方案。
由于这是一个消耗性操作,它只能与不返回任何东西的方法一起使用;也就是说,使用forEach
确保了终端操作,在这种操作中你不会得到返回值。
如果你想验证属性设置是否符合你的要求,你需要再次检查元素。
users.stream().filter(u -> u.count > 0)
.allMatch(u -> u.getProperty().equals("value"));
虽然这更多的是针对偏执狂而言;除非 setProperty
有其他未暴露的副作用,否则 setter 应该 始终 设置值。 我会将上述内容编写为单元测试以进行验证,但不会在生产代码中使用。
peek
实际上只是用于调试目的(参见https://dev59.com/XFwX5IYBdhLWcg3wlwWQ)。 - Makoto添加一个调用 peek()
:
AtomicBoolean modified = new AtomicBoolean();
users.stream()
.filter(u -> u.count > 0)
.peek(u -> modified.set(true))
.forEach(u -> u.setProperty("value"))
modified.get()
将返回 true
。AtomicBoolean
(或类似物)是必需的,因为在 lambda 中使用的引用必须是有效的 final。peek
的话,为什么不使用boolean modified = users.stream().filter(u -> u.count > 0).peek(u -> u.setProperty("value")).count() > 0;
呢?这样就不需要用到AtomicBoolean
。另一方面,如果你使用了AtomicBoolean
,你就不需要使用peek
了:users.stream().filter(u -> u.count > 0).forEach(u -> { modified.set(true); u.setProperty("value"); });
。 - Holgerpeek()
来设置标志不会改变 OP 现有的代码 - 它很容易添加和删除。它不会将修改检测嵌入到主代码中 - 参见关注点分离。每个流方法正在做什么以及为什么调用它是清晰的。在这种情况下,peek()
是正确的方法。 - Bohemianpeek
内的操作将停止工作,因此不存在真正的“责任分离”,而是一个不太明显的依赖关系。 - Holger
setProperty
返回什么?一个boolean
吗? - Andrew TobilkosetProperty
后,对象不会被修改? - Andrew Tobilko