基于另一个列表的1个列表的流过滤器 [英] Stream Filter of 1 list based on another list

查看:130
本文介绍了基于另一个列表的1个列表的流过滤器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此论坛中搜索后,我正在发布查询.谷歌,但无法解决同样的问题. 例如: Link1 Link3

I am posting my query after having searched in this forum & google, but was unable to resolve the same. eg: Link1 Link2 Link3

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

I am trying to filter List 2 (multi column) based on the values in List 1.

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]

代码

Code

// 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中的Car Name是否在列表1中退出.

In the above code if I provide a specific value I can filter, but not sure how to check if Car Name in List 2 exits in List 1.

希望我遇到的问题很清楚,等待指导(对于Java来说还比较陌生,因此如果上面的查询非常基础,请原谅.)

Hope the issue I face is clear, await guidance (Am still relatively new to Java, hence forgive if the above query is very basic).

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

Edit I believe the link-3 provided above should resolve, but in my case it is not working. Maybe because the values in list-1 are populated as org.gradle04.Main.Cars.dataCarName@4148db48 .. etc. I am able to get the value in human readable format only when I do a forEach on List 1 by calling the getName method.

推荐答案

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

It's not clear why you have a List<DataCarName> in first place instead of a List/Set<String>.

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

The predicate you have to provide must check if for the corresponding data car instance, there's its name in the list.

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

e -> e.getName().contains("BMW") will only check if the name of the data car contains BMW which is not what you want. Your first attempt then may be

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

,但由于listCarNameList<DataCarName>,而e.getName()是字符串(我想),因此您将获得一个空列表.

but since listCarName is a List<DataCarName> and e.getName() a string (I presume), you'll get an empty list as a result.

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

The first option you have is to change the predicate so that you get a stream from the list of data car names, map them to their string representation and check that any of these names corresponds to the current data car instance's name you are currently filtering:

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

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

Now this is very expensive because you create a stream for each instance in the data car stream pipeline. A better way would be to build a Set<String> with the cars' name upfront and then simply use contains as a predicate on this set:

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

这篇关于基于另一个列表的1个列表的流过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆