首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 8 streams中的if-else if-else功能

Java 8 streams中的if-else if-else功能
EN

Stack Overflow用户
提问于 2017-01-04 01:13:20
回答 5查看 9.3K关注 0票数 2

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

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

现在,当涉及到代码时,我希望是这样的:

代码语言:javascript
复制
  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?
  }
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2017-01-04 02:40:29

您可以使用

代码语言:javascript
复制
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;
}

这会将每个元素映射到它的侧边计数,并将它们减少到首选类型,这恰好是这里的最大计数,因此不需要自定义的缩减函数。

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

代码语言:javascript
复制
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。因此,这将搜索第一个元素,即RECTHEXA。如果没有,则返回GENERIC;否则,如果第一个不是HEXA,则检查其余元素是否为HEXA类型的元素。注意,对于处理第一个RECT之后的剩余部分,不需要filter,因为这意味着既不是RECT也不是HEXA的形状不能满足条件。

但也应该清楚的是,这段试图最小化检查次数的代码比等效的for循环更难阅读。

票数 5
EN

Stack Overflow用户

发布于 2017-01-04 01:35:45

假设列表中只有三种类型的形状,另一种方法是:

代码语言:javascript
复制
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循环:

代码语言:javascript
复制
ShapeType st = GENERIC;
for (Shape s : shapes) {
  if (s.getSideCount() == 6) return HEXA;
  if (s.getSideCount() == 4) st = RECTANGLE;
}
return st;
票数 4
EN

Stack Overflow用户

发布于 2017-01-04 01:25:54

如果我理解你想做什么,那么你可以使用anyMatch。比如,

代码语言:javascript
复制
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流式传输)的一种方法是使用数组保留形状。比如,

代码语言:javascript
复制
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;
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41448826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档