if elseif else like java 8流的功能

j1dl9f46  于 2021-07-12  发布在  Java
关注(0)|答案(5)|浏览(205)

我有一个物体列表,比如说形状。我想使用流处理它们,并根据列表中的内容返回另一个对象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?
  }
fcg9iug3

fcg9iug31#

你可以用

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;
}

这将每个元素Map到它的边计数,并将它们减少到首选类型,这恰好是这里的最大计数,因此不需要自定义的减少函数。
这不是短路,但对于大多数用例来说,这就足够了。如果你想把操作的次数减少到必要的最低限度,事情会更复杂。

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 循环。

blmhpbnm

blmhpbnm2#

假设列表中只能显示这三种类型的形状,另一种选择是:

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;
ijxebb2r

ijxebb2r3#

如果我明白你想做什么,那你可以用 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 一次)将保留数组的形状。比如,

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;
    }
}
nkoocmlb

nkoocmlb4#

也可以这样做:

ShapeType r = shapes.stream()
        .map(s -> ShapeType.parse(s.getSides()))
        .filter(c -> c == ShapeType.Hexagon || c==ShapeType.Square)
        .max(ShapeType::compareTo)
        .orElse(ShapeType.Generic);

在这里,我和你的朋友有点自由 ShapeType :

enum ShapeType {
    Square(4), Hexagon(6), Generic(Integer.MAX_VALUE);
    int v;
    ShapeType(int v) {
      this.v = v;
    }
    static ShapeType parse(int v) {
      switch (v) {
        case 4: return Square;
        case 6: return Hexagon;
        default:
          break;
      }
      return Generic;
    }
    public String toString(){
      return Integer.toString(v);
    }
  }

tbh如果添加 getShapeType() 方法,该方法为每个派生类型返回正确的类型。然后 map() 例如,操作将只提取类型 .map(Shape::getShapeType) .
这个 .filter() 会发现你感兴趣的群体,最大的形状被认为是集合的标签。。。

tkqqtvp1

tkqqtvp15#

听起来像是“reduce”或“collect/max”的例子。
假设您有一个选择“支配”类型的方法(您可以将它放在lambda中,但是作为一个方法,它更可读):

public class Util{
    public static ShapeType dominantType(ShapeType t1, ShapeType t2){
        if(t1==HEXA || t2==HEXA) return HEXA;
        else if (t1==RECTANGLE || t2==RECTANGLE) return RECTANGLE;
        else return GENERIC;
    }
}

有几种方法可以使用它,例如:

shapes.stream()
.filter(shape -> shape.getSideCount() == 6 || shape.getSideCount() == 4)
.map(shape -> shape.getSideCount()==6? HEXA:RECTANGLE)
.reduce( GENERIC,  Util::dominantType); 
 //   using GENERIC in case of empty list

您可能还需要查看collectors.maxby。顺便说一句,无论你采取什么方法,请给一些思考的行为,以防一个空名单。。。

相关问题