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

pn9klfpd  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(390)

我发布我的查询后,在这个论坛和谷歌搜索,但无法解决相同的问题。例如:链接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应该解决,但在我的情况下,它不工作。可能是因为列表1中的值填充为org.gradle04.main.cars。datacarname@4148db48 .. 只有在调用getname方法对列表1执行foreach操作时,我才能以可读的格式获取值。

fcwjkofz

fcwjkofz1#

在你的数据车里,是吗 getName() 返回字符串还是datacarname枚举类型?如果是enum,您可能会遵循alexis c的方法,但不是使用collectors.toset()构建hashset,而是构建一个enumset,这样可以提供o(1)性能。修改alexis的建议,结果如下:

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

p1iqtdky2#

不清楚你为什么有 List<DataCarName> 首先,而不是 List/Set<String> .
必须提供的 predicate 必须检查对应的数据车示例是否在列表中有其名称。 e -> e.getName().contains("BMW") 只会检查数据车的名称是否包含宝马这不是你想要的。你的第一次尝试可能是

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

但是自从 listCarName 是一个 List<DataCarName> 以及 e.getName() 一个字符串(我猜),你会得到一个空列表作为结果。
第一个选项是更改 predicate ,以便从数据车名称列表中获取流,将它们Map到它们的字符串表示形式,并检查这些名称是否与当前正在筛选的数据车示例的名称对应:

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

现在这是非常昂贵的,因为您为数据流管道中的每个示例创建一个流。更好的方法是建立一个 Set<String> 把车的名字写在前面 contains 作为此集合的 predicate :

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

相关问题