2015-12-04 42 views
0

我有一個列表Car s,其中每輛車都有一個通過Engine界面定義的引擎。在這個例子中,具體類型是CombustionEngine,可變數量的柱面和ElectricMotor從Java 8流中過濾引用具有某個屬性的某個子類型的元素

我想找到所有(燃燒)四缸發動機。使用Java流,我想出了這條管道:

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

雖然這個作品,我想知道是否有可能避免投在第二filter謂語或完全重寫的管道是更具可讀性?


參考,爲了與我對experiemnt已經連接的例子的完整源:

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); 
    } 
} 
+0

可能重複[是否可以在Java 8中投射流?](http://stackoverflow.com/questions/22511750/is-it-possible-to-cast-a-stream-in-java- 8) –

回答

1

我不認爲這是可能避免的演員。畢竟,CarEngine都不能提供任何可以區分電動汽車和ICE汽車的方法。

但是,如果你的Engine沒有方法,在我看來這意味着它應該無關緊要,它是什麼樣的引擎。

我能想出的最好的是

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

,但我不知道這是否是更具可讀性。

相關問題