【问题标题】:Is this possible with Java StreamJava Stream 有可能吗
【发布时间】:2016-06-04 23:44:30
【问题描述】:

我只是要求兴趣。是否可以通过使用 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());
    }
});

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

【问题讨论】:

  • 为什么不toys.map(toy -&gt; /* your code here */).collect(Collectors.toSet)?附言你为什么要投给BikeSkateBoard
  • 澄清你想要达到的效果。

标签: java foreach java-stream


【解决方案1】:

这不是利用继承的正确方法。更好的方法是有类似的东西

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

【讨论】:

  • 是的。这。总是这个。你也可以使用双重调度;但这可能有点矫枉过正......
  • 我不可能在超类中做到这一点。我为此做了一个糟糕的示例代码。想想轮子的数量或类似的东西。没有任何玩具有轮子,所以该方法不存在。是否可以在不将所有方法放入超类的情况下使用流?
  • @MysteriousPerson:并非没有反思。在这种情况下,一个好的设计是在超类中有一个方法,比如bool supportsFeature(Feature feature),这样你就可以做stream().filter(t -&gt; t.supportsFeature(Feature.WHEELS)).map(...)
  • 谢谢。你的实际例子给了我一些启发。我为此使用了一个界面:)
  • @MysteriousPerson:检查我的编辑,您也可以使用多种接口来获取您要查找的内容。唯一的缺点是你必须使用向下转换,如果在这种情况下它是安全的,你也应该始终避免这样做。
猜你喜欢
  • 2018-08-14
  • 2011-11-29
  • 2023-03-19
  • 1970-01-01
  • 2015-08-18
  • 2011-10-09
  • 1970-01-01
  • 2011-10-12
  • 1970-01-01
相关资源
最近更新 更多