我有一个对象列表,比如说形状。我想使用一个流来处理它们,并根据列表中的内容返回另一个对象- ShapeType。
通常我只返回ShapeType.GENERIC,但是如果里面有矩形,我想返回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?
}发布于 2017-01-04 02:40:29
您可以使用
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处停止,但为了避免第二次遍历,有必要记住在没有HEXA的情况下是否出现了RECT。因此,这将搜索第一个元素,即RECT或HEXA。如果没有,则返回GENERIC;否则,如果第一个不是HEXA,则检查其余元素是否为HEXA类型的元素。注意,对于处理第一个RECT之后的剩余部分,不需要filter,因为这意味着既不是RECT也不是HEXA的形状不能满足条件。
但也应该清楚的是,这段试图最小化检查次数的代码比等效的for循环更难阅读。
发布于 2017-01-04 01:35:45
假设列表中只有三种类型的形状,另一种方法是:
Set<Integer> sides = shapes.stream()
.map(Shape::getSideCount)
.collect(toSet());
if (sides.contains(6)) return HEXA;
else if (sides.contains(4)) return RECTANGLE;
else return GENERIC;但我认为最直接(也是最有效)的方法是一个很好的for循环:
ShapeType st = GENERIC;
for (Shape s : shapes) {
if (s.getSideCount() == 6) return HEXA;
if (s.getSideCount() == 4) st = RECTANGLE;
}
return st;发布于 2017-01-04 01:25:54
如果我理解你想做什么,那么你可以使用anyMatch。比如,
public ShapeType resolveShapeType(final List<Shape> shapes) {
if (shapes.stream().anyMatch(shape -> shape.getSideCount() == 6)) {
return ShapeType.HEXA;
} else if (shapes.stream().anyMatch(shape -> shape.getSideCount() == 4)) {
return ShapeType.RECT;
} else {
return ShapeType.GENERIC;
}
}要做到这一点( shapes once流式传输)的一种方法是使用数组保留形状。比如,
public ShapeType resolveShapeType(final List<Shape> shapes) {
boolean[] bits = new boolean[2];
shapes.stream().forEach(shape -> {
int sides = shape.getSideCount();
if (sides == 4) {
bits[0] = true;
} else if (sides == 6) {
bits[1] = true;
}
});
if (bits[1]) {
return ShapeType.HEXA;
} else if (bits[0]) {
return ShapeType.RECT;
} else {
return ShapeType.GENERIC;
}
}https://stackoverflow.com/questions/41448826
复制相似问题