将两个流合并成一个

时间:2020-10-26 16:02:00

标签: 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.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");
}

// ...

代码工作正常,但是我不满意需要在流中迭代两次。

我能以某种方式一次获得相同的结果吗?

1 个答案:

答案 0 :(得分:1)

该代码压缩为:

  • 不操作检查(新名称为旧名称)
  • 所有动物不包含这个新名称
  • 您可以用它的旧名字找到动物

所以:

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
}

使用HashMap可以使速度更快。

您可以在一个流中最多收集2个动物的旧名称或新名称。但它不会改变时间复杂度:N个步和一个分支。同样,只有在收集的结果大小为2时,才可以停止循环。这肯定看起来并不好。 2单独的查询可以更快。