基于另一个列表的 1 个列表的流过滤器

新手上路,请多包涵

我在此论坛和谷歌中搜索后发布了我的查询,但无法解决相同的问题。例如: 链接 1 链接2 链接 3

我正在尝试根据列表 1 中的值过滤列表 2(多列)。

 List1:
 - [Datsun]
 - [Volvo]
 - [BMW]
 - [Mercedes]

List2:
 - [1-Jun-1995, Audi, 25.3, 500.4, 300]
 - [7-Apr-1996, BMW, 35.3, 250.2, 500]
 - [3-May-1996, Porsche, 45.3, 750.8, 200]
 - [2-Nov-1998, Volvo, 75.3, 150.2, 100]
 - [7-Dec-1999, BMW, 95.3, 850.2, 900]

expected o/p:
 - [7-Apr-1996, BMW, 35.3, 250.2, 500]
 - [2-Nov-1998, Volvo, 75.3, 150.2, 100]
 - [7-Dec-1999, BMW, 95.3, 850.2, 900]

代码

// List 1 in above eg
List<dataCarName> listCarName = new ArrayList<>();
// List 2 in above eg
List<dataCar> listCar = new ArrayList<>();

// Values to the 2 lists are populated from excel

List<dataCar> listOutput = listCar.stream().filter(e -> e.getName().contains("BMW")).collect(Collectors.toList());

在上面的代码中,如果我提供了一个可以过滤的特定值,但不确定如何检查列表 2 中的汽车名称是否存在于列表 1 中。

希望我面临的问题很清楚,等待指导(我对 Java 还比较陌生,因此如果上述查询非常基本,请原谅)。

编辑 我相信上面提供的链接 3 应该可以解决,但在我的情况下它不起作用。可能是因为 list-1 中的值填充为 org.gradle04.Main.Cars.dataCarName@4148db48 .. 等等。只有当我通过调用 getName 在 List 1 上执行 forEach 时,我才能以人类可读格式获取值方法。

原文由 iCoder 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 675
2 个回答

目前尚不清楚为什么您首先使用 List<DataCarName> 而不是 List/Set<String>

您必须提供的谓词必须检查相应数据车实例的列表中是否有其名称。

e -> e.getName().contains("BMW") 只会检查数据车的名称是否包含您不想要的宝马。那么你的第一次尝试可能是

e -> listCarName.contains(e.getName())

但由于 listCarNameList<DataCarName>e.getName() 一个字符串(我想),你会得到一个空列表作为结果。

您拥有的第一个选项是更改谓词,以便从数据车名称列表中获取一个流,将它们映射到它们的字符串表示形式,并检查这些名称中的任何一个是否与您当前正在过滤的当前数据车实例的名称相对应:

 List<DataCar> listOutput =
    listCar.stream()
           .filter(e -> listCarName.stream().map(DataCarName::getName).anyMatch(name -> name.equals(e.getName())))
           .collect(Collectors.toList());

现在这非常昂贵,因为您为数据汽车流管道中的每个实例创建一个流。更好的方法是先构建一个 Set<String> 带有汽车的名称,然后简单地使用 contains 作为这个集合的谓词:

 Set<String> carNames =
    listCarName.stream()
               .map(DataCarName::getName)
               .collect(Collectors.toSet());

List<DataCar> listOutput =
     listCar.stream()
            .filter(e -> carNames.contains(e.getName()))
            .collect(Collectors.toList());

原文由 Alexis C. 发布,翻译遵循 CC BY-SA 3.0 许可协议

在您的 DataCar 类型中, getName() 返回 String 或 DataCarName 枚举类型?如果它是枚举,您可以遵循 Alexis C 的方法,但不是使用 Collectors.toSet() 构建 HashSet,而是构建 EnumSet,它提供 O(1) 性能。修改亚历克西斯的建议,结果如下:

 Set<DataCarName> carNames =
    listCarName.stream()
               .collect(Collectors.toCollection(
                   ()-> EnumSet.noneOf(DataCarName.class)));

List<DataCar> listOutput =
    listCar.stream()
               .filter(car -> carNames.contains(car.getName()))
               .collect(Collectors.toList());

原文由 Hank D 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题