这是Java Stream的可能吗?

时间:2016-06-04 23:44:31

标签: java foreach java-stream

我只想要感兴趣。是否有可能通过使用Java的Stream来制作这样的东西? (将是toys.stream()...)

Set<String> colors = new HashSet<>();

toys.forEach((toy) -> {
    if (toy.getType() == Toys.BIKE) {
        colors.add(((Bike) toy.getData()).getFrameColor());
    } else {
        colors.add(((Skateboard) toy.getData()).getColor());
    }
});

我应该提一下,我不可能将颜色存储在超类中。

1 个答案:

答案 0 :(得分:4)

这不是利用继承的正确方法。更好的方法是拥有像

这样的东西
abstract class Toy {
  abstract Color getActualColor();
}

class Bike {
  @Override Color getActualColor() { return getFrameColor(); }
}

class Skateboard {
  @Override Color getActualColor() { return getColor(); }
}

...
toys.stream().map(Toy::getActualColor).collect(Collectors.toSet());

它利用了多态性,因此您不必在运行时检查实例的类型,这在99%的时间都是不好的。请注意,您的设计似乎是Toy内的组合数据,而不是

class Toy {
  ToyData data;
}

但设计没有改变,你只需要两次映射,例如stream().map(Toy::getData).map(ToyData::getActualColor)

根据您的编辑,解决方案必须使用一组接口来标记各种功能,例如:

class Toy
{
    final ToyData data;

    public Toy(ToyData data) { this.data = data; }

    public ToyData getData() { return data; }
}

interface ToyData { } 

interface Colored
{
    Color getColor();
}

class Bike implements ToyData, Colored
{
    @Override public Color getColor() { return Color.WHITE; }
}

class Skateboard implements ToyData, Colored
{
    @Override public Color getColor() { return Color.BLACK; }
}

class Ship implements ToyData { }


public static void main (String[] args) throws java.lang.Exception
{
    List<Toy> toys = new ArrayList<>();

    toys.add(new Skateboard());
    toys.add(new Bike());
    toys.add(new Ship());

    Set<Color> = toys.stream()
                     .map(Toy::getData)
                     .filter(t -> t instanceof Colored)
                     .map(t -> ((Colored)t).getColor())
                     .collect(Collectors.toSet());
}