【问题标题】:Filter elements from a Java 8 stream that reference a certain subtype with a certain attribute从 Java 8 流中过滤引用具有特定属性的特定子类型的元素
【发布时间】:2016-03-09 23:19:09
【问题描述】:

我有一个Cars 列表,其中每辆车都有一个通过Engine 接口定义的引擎。在这个例子中,具体类型是CombustionEngine,具有可变数量的柱面,以及ElectricMotor

我想找到所有四缸(燃烧)发动机。使用 Java 流我想出了这个管道:

Car[] carsWithFourCylinders
  = cars.stream()
  .filter( car -> car.engine instanceof CombustionEngine )
  .filter( car -> ( ( CombustionEngine )car.engine ).cylinderCount == 4 )
  .toArray( Car[]::new );

虽然这可行,但我想知道是否可以在第二个 filter 谓词中避免强制转换,或者完全重写管道以提高可读性?


为了参考和实验,我附上了示例的完整源代码:

public class CarTest {

  interface Engine { }

  class CombustionEngine implements Engine {
    final int cylinderCount;

    CombustionEngine( int cylinderCount ) {
      this.cylinderCount = cylinderCount;
    }
  }

  class ElectricMotor implements Engine { }

  class Car {
    final Engine engine;

    Car( Engine engine ) {
      this.engine = engine;
    }
  }

  @Test
  public void filterCarsWithFourCylinders() {
    List<Car> cars = Arrays.asList( new Car( new CombustionEngine( 4 ) ), 
                                    new Car( new ElectricMotor() ), 
                                    new Car( new CombustionEngine( 6 ) ) );

    Car[] carsWithFourCylinders
      = cars.stream()
      .filter( car -> car.engine instanceof CombustionEngine )
      .filter( car -> ( ( CombustionEngine )car.engine ).cylinderCount == 4 )
      .toArray( Car[]::new );


    assertEquals( 1, carsWithFourCylinders.length );
  }
}

【问题讨论】:

标签: java-stream


【解决方案1】:

我认为避免演员表是不可能的。毕竟,CarEngine 都没有提供任何方法来区分电动汽车和配备 ICE 的汽车。

但是如果你的Engine 没有方法,在我看来这意味着Car 它拥有什么样的引擎应该无关紧要。

我能想到的最好的是

   final List<Car> combustionCars = cars.stream()
            .collect(groupingBy(c -> c.engine.getClass()))
            .get(CombustionEngine.class);
    long count = combustionCars
            .stream()
            .map(Car::getEngine)
            .map(CombustionEngine.class::cast)
            .filter(c -> c.cylinderCount == 4).collect(Collectors.counting());

但我不确定这是否更具可读性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    相关资源
    最近更新 更多