根据另一个列表对1个列表进行流过滤

iCo*_*der 28 java-8 java-stream

我在这个论坛和谷歌搜索后发布我的查询,但无法解决相同问题.例如:Link1 Link2 Link3

我试图根据列表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]
Run Code Online (Sandbox Code Playgroud)

// 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());
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,如果我提供了一个特定的值,我可以过滤,但不知道如何检查List 2中的Car Name是否在List 1中退出.

希望我面临的问题很明确,等待指导(对Java来说还是比较新的,因此如果上面的查询非常基本,请原谅).

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

Ale*_* C. 52

目前尚不清楚为什么你有一个List<DataCarName>在第一位而不是一个List/Set<String>.

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

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

e -> listCarName.contains(e.getName())
Run Code Online (Sandbox Code Playgroud)

但由于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());
Run Code Online (Sandbox Code Playgroud)

现在这非常昂贵,因为您为数据汽车流管道中的每个实例创建了一个流.一个更好的方法是先建立一个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());
Run Code Online (Sandbox Code Playgroud)


Han*_*k D 7

在您的DataCar类型中,是否getName()返回String或DataCarName枚举类型?如果它是枚举,您可以遵循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());
Run Code Online (Sandbox Code Playgroud)