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");
}

// ...
代码运行得很好,但我不高兴我需要在流上迭代两次

我能一次达到同样的效果吗?

代码浓缩为:

  • 无操作检查(新名称为旧名称)
  • 所有动物不包含此新名称
  • 你可以通过它的旧名字找到它
因此:

一个关键的改进是能够通过名字找到动物

一个HashMap会让速度更快


你可以在一条溪流中收集最多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
}