Java 将两条流合并为一条流
考虑以下代码:Java 将两条流合并为一条流,java,java-8,java-stream,Java,Java 8,Java Stream,考虑以下代码: // ... String currentName = ... String newName = ...; // possibly same as currentName. // in such a case, no exception should be thrown AnimalEntity animal = animalKeeper.getAnimals() .stream() .filter(a -> a
// ...
String currentName = ...
String newName = ...; // possibly same as currentName.
// in such a case, no exception should be thrown
AnimalEntity animal = animalKeeper.getAnimals()
.stream()
.filter(a -> a.getName().equals(currentName))
.findFirst()
.orElseThrow(() -> new NoResourceException("No animal with that name"));
if (animalKeeper.getAnimals()
.stream()
.filter(a -> !a.getName().equals(currentName))
.anyMatch(a -> a.getName().equals(newName))) {
throw new BadRequestException("You already have animal with that name");
}
// ...
代码运行得很好,但我不高兴我需要在流上迭代两次
我能一次达到同样的效果吗?代码浓缩为:
- 无操作检查(新名称为旧名称)
- 所有动物不包含此新名称
- 你可以通过它的旧名字找到它
你可以在一条溪流中收集最多2只动物,它们的名字是旧的或新的。但它并没有改变任何时间复杂性:N个步骤,一个分支。此外,您只能在收集的结果大小为2时停止循环。这看起来肯定不会更好。两个单独的查询可以更快。如果您想在出错时抛出两个不同的异常,您确定要合并这两个流吗?我相信
currentName
实际上是在第二个流中找到并过滤掉的anyMatch
操作的是animalKeeper
的一个子集,该子集不包含currentName
,因此您已经有了名为animal的语句。第一个流不会处理所有元素。它在第一场比赛时停止。当currentName.equals(newName)
时,可以完全跳过第二个,这很容易事先检查。因此,将两个操作融合为一个操作将导致一个操作必须执行更多的工作。@Naman它不再是相同的。在最初的问题中,currentName是在第一个流求值之后设置的,这取决于第一个流聚合的结果。现在你把它任意化了,这完全改变了它的意思。@Naman是的,我错过了。回到我最初的问题“你们已经有了那个名字的动物”在逻辑上是不正确的,因为由于在第一个流中抛出异常,这种情况永远不会出现。findAny
不接受参数。因此它必须是filter(predicate).findAny()
,就像OP的代码一样。地图方法可用,但地图中包含的对象不应引用地图,因此,Animal
的rename
方法不应负责更新地图。您可以将get
调用替换为remove
,并且已经完成了一半的工作。当您检查containsKey(newName)
时,您还应该在重命名调用中使用newName
。@Holger findAny更正。我不想写getMap()。get(…)
和getByName
这两个选项都没有显示任何映射性。我没有建议写getMap()
。首先,您执行containsKey(newName)
检查,然后执行animal.rename(“Koniara”)
。这是不一致的。此外,整行animal.rename(“Koniara”);//remove+put
表示此方法负责更新实际位于animalKeeper
中的地图。但是动物
不应该做动物饲养员
的工作。哦,你把orelsetrow
的语法搞错了。它应该是.orelsetrow(()->new NoResourceException(“没有这个名字的动物”)
参数是异常的提供者,而不是一个throw
语句。@Holger我会改进自己;花的时间太少了
if (!newName.equals(oldName)) {
if (animalKeeper.getAnimals().stream()
.anyMatch(a -> a.getName().equals(newName))) {
throw new BadRequestException("You already have animal with that name");
}
Animal animal = animalKeeper.getAnimals().stream()
.filter(a -> a.getName().equals(oldName))
.findAny()
.orElseThrow(throw new NoResourceException("No animal with that name"));
animal.rename("Koniara");
}
if (!newName.equals(oldName)) {
if (animalKeeper.mapByName.containsKey(newName)) {
throw new BadRequestException("You already have animal with that name");
}
Animal animal = animalKeeper.mapByName.get(oldName);
if (animal == null) {
throw new NoResourceException("No animal with that name"));
}
animal.rename("Koniara"); // remove+put
}