当前位置: 首页 > 知识库问答 >
问题:

Java 8流中引用具有特定属性的特定子类型的筛选器元素

钱峻
2023-03-14

我有一个汽车列表,其中每辆汽车都有一个发动机,该发动机是通过界面定义的。在本例中,具体类型为具有可变气缸数的燃烧发动机和电动机。

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

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

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

为了便于参考和体验,我附上了示例的完整来源:

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

共有1个答案

羊舌高爽
2023-03-14

我认为避免演员阵容是不可能的。毕竟,无论是汽车还是发动机,都没有提供任何方法来区分电动汽车和内燃机汽车。

但是,如果您的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());

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

 类似资料:
  • 问题内容: 在XML文档中,我具有共享相同名称的元素,但是属性的值定义了它是什么类型的数据,并且我想从文档中选择所有具有特定值的元素。我是否需要使用XPath(如果可以,您是否可以建议正确的语法)还是有更优雅的解决方案? 这是一些示例XML: 我想选择类型为的所有子代标签的内容。 PS-我正在尝试使用PHP与Netflix API进行接口-这对我的问题无关紧要,但是如果您想提出一种更好的方法,我非

  • 问题内容: 我试图通过将所有参数元素为type_id =“ 4218”的所有“ ”元素从URL解析XML文件? XML文件: 这是我的Java代码: 这段代码给了我所有元素,我不想要,我想要属性type_id =“ 4218”的所有元素! 问题答案: XPath是您的正确选择: 并遍历

  • 问题内容: 可以说我们有以下代码: 您将如何选择第一个属性等于3的孩子?我在想,也许这可以做到: …但是没有用 问题答案: 该伪类仅着眼于第一子节点,因此,如果第一个孩子是不是,则选择一无所有。 没有类似的属性过滤器伪类。一种简单的解决方法是选择每个对象,然后排除第一个对象之后的内容 当然,这仅适用于样式。如果您要出于样式之外的目的挑选该元素(因为标记看起来是任意XML而不是HTML),则必须使用

  • 嗨,我有以下XML 标准是只复制“item-name”属性值为TShert、Ball或Bat的位置。所以生成的XML应该看起来像 我正在使用以下XSLT 但这不起作用。你能帮忙吗? 谢谢Nathan

  • 我还有这个包含ID列表: 我想筛选以便筛选的不包含id来自的对象,因此我尝试使用stream: 我找不到做这件事的正确函数。有人有什么建议让我试试吗?

  • 问题内容: 我想筛选一个像这样的选择: 编辑:添加列模型: 列用于多种用途,并且为了优化我的代码,我需要将其也包含在Select中,但没有类型为“字段”或“映射”的条目 但是,我可以从所有内容中进行选择,甚至包括类型为“字段”和“地图”的条目。有没有一种清洁的方法? 问题答案: AngularJS NOT过滤器 小提琴 从 文档 : “ …谓词可以通过在字符串前面加上!来取反。” “模式对象可用于