我有一个对象列表,可以说形状。
我想使用流来处理它们,并根据列表中的内容返回另一个对象-ShapeType。

通常,我只返回ShapeType.GENERIC,但是如果其中存在Rectangle,我想返回ShapeType.RECT。如果列表中有六角形,我想返回ShapeType.HEXA。
当同时存在矩形和正方形时,我想返回ShapeType.HEXA。

现在,当涉及到代码时,我想要这样的东西:

  public ShapeType resolveShapeType(final List<Shape> shapes) {
    shapes.stream()
    .filter(shape -> shape.getSideCount() == 6 || shape.getSideCount() == 4)
    // I should have a stream with just rectangles and hexagons if present.
    // what now?
  }

最佳答案

您可以使用

public ShapeType resolveShapeType(final List<Shape> shapes) {
    int sides = shapes.stream()
        .mapToInt(Shape::getSideCount)
        .filter(count -> count==4 || count==6)
        .max().orElse(0);
    return sides==6? ShapeType.HEXA: sides==4? ShapeType.RECT: ShapeType.GENERIC;
}


这会将每个元素映射到其边数,并将其减少为首选类型,该类型恰好是此处的最大数量,因此不需要自定义归约功能。

这不是短路,但是对于大多数使用情况来说,就足够了。如果要将操作次数减少到必要的最低限度,事情将会变得更加复杂。

public ShapeType resolveShapeType(final List<Shape> shapes) {
    OptionalInt first = IntStream.range(0, shapes.size())
        .filter(index -> {
            int count = shapes.get(index).getSideCount();
            return count == 6 || count == 4;
        })
        .findFirst();
    if(!first.isPresent()) return ShapeType.GENERIC;
    int ix = first.getAsInt(), count = shapes.get(ix).getSideCount();
    return count==6? ShapeType.HEXA: shapes.subList(ix+1, shapes.size()).stream()
        .anyMatch(shape -> shape.getSideCount()==6)? ShapeType.HEXA: ShapeType.RECT;
}


我们知道我们可以在第一个HEXA处停下来,但是为了避免第二遍,必须记住在没有RECT的情况下是否出现了HEXA。因此,这将搜索第一个元素RECTHEXA。如果不存在,则返回GENERIC,否则,如果第一个不是HEXA,则检查其余元素是否为HEXA类型的元素。请注意,要处理第一个RECT之后的余数,不需要filter,因为这意味着RECTHEXA都不符合该条件。

但是也很明显,此代码试图最小化检查次数,比等效的for循环更难阅读。

08-26 12:14