我有一个对象列表,可以说形状。
我想使用流来处理它们,并根据列表中的内容返回另一个对象-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
。因此,这将搜索第一个元素RECT
或HEXA
。如果不存在,则返回GENERIC
,否则,如果第一个不是HEXA
,则检查其余元素是否为HEXA
类型的元素。请注意,要处理第一个RECT
之后的余数,不需要filter
,因为这意味着RECT
或HEXA
都不符合该条件。但是也很明显,此代码试图最小化检查次数,比等效的
for
循环更难阅读。