简体   繁体   English

使用java 8迭代和过滤两个列表

[英]iterating and filtering two lists using java 8

I want to iterate two lists and get new filtered list which will have values not present in second list.我想迭代两个列表并获取新的过滤列表,该列表的值将不存在于第二个列表中。 Can anyone help?任何人都可以帮忙吗?

I have two lists - one is list of strings, and the other is list of MyClass objects.我有两个列表——一个是字符串列表,另一个是MyClass对象列表。

List<String> list1;
List<MyClass> list2;

MyClass {

    MyClass(String val)
    {
        this.str = val;
    }

     String str;
     ...
     ...
}

I want filtered list of strings based on -> check second list for elements (abc) whose values not present in list1 .我想要基于过滤的字符串列表 -> 检查其值不在list1元素(abc)的第二个列表。

List<String> list1 = Arrays.asList("abc", "xyz", "lmn");

List<MyClass> list2 = new ArrayList<MyClass>();

MyClass obj = new MyClass("abc");
list2.add(obj);
obj = new MyClass("xyz");
list2.add(obj);

Now I want new filtered list -> which will have value => "lmn".现在我想要新的过滤列表 -> 它将具有值 =>“lmn”。 ie values not present in list2 whose elements are in list1 .即元素在list1中的list2不存在list1

// produce the filter set by streaming the items from list 2
// assume list2 has elements of type MyClass where getStr gets the
// string that might appear in list1
Set<String> unavailableItems = list2.stream()
    .map(MyClass::getStr)
    .collect(Collectors.toSet());

// stream the list and use the set to filter it
List<String> unavailable = list1.stream()
            .filter(e -> unavailableItems.contains(e))
            .collect(Collectors.toList());

this can be achieved using below...这可以使用下面的方法来实现......

 List<String> unavailable = list1.stream()
                            .filter(e -> !list2.contains(e))
                            .collect(Collectors.toList());

Doing it with streams is easy and readable:使用流来做这件事很容易且可读:

Predicate<String> notIn2 = s -> list2.stream().noneMatch(mc -> s.equals(mc.str));
List<String> list3 = list1.stream().filter(notIn2).collect(Collectors.toList());

If you stream the first list and use a filter based on contains within the second...如果您流式传输第一个列表并使用基于包含在第二个列表中的过滤器...

list1.stream()
    .filter(item -> !list2.contains(item))

The next question is what code you'll add to the end of this streaming operation to further process the results... over to you.下一个问题是您将在此流操作的末尾添加什么代码以进一步处理结果……交给您。

Also, list.contains is quite slow, so you would be better with sets.此外, list.contains 很慢,所以你会更好地使用集合。

But then if you're using sets, you might find some easier operations to handle this, like removeAll但是如果你使用集合,你可能会发现一些更简单的操作来处理这个,比如 removeAll

Set list1 = ...;
Set list2 = ...;
Set target = new Set();
target.addAll(list1);
target.removeAll(list2);

Given we don't know how you're going to use this, it's not really possible to advise which approach to take.鉴于我们不知道您将如何使用它,因此不太可能建议采取哪种方法。

See below, would welcome anyones feedback on the below code.见下文,欢迎任何人对以下代码提供反馈。

not common between two arrays:两个数组之间不常见:

List<String> l3 =list1.stream().filter(x -> !list2.contains(x)).collect(Collectors.toList());

Common between two arrays:两个数组之间的共同点:

List<String> l3 =list1.stream().filter(x -> list2.contains(x)).collect(Collectors.toList());
list1 = list1.stream().filter(str1-> 
        list2.stream().map(x->x.getStr()).collect(Collectors.toSet())
        .contains(str1)).collect(Collectors.toList());

This may work more efficient.这可能更有效。

if you have class with id and you want to filter by id如果你有带 id 的类并且你想按 id 过滤

line1 : you mape all the id line1 : 你映射所有的 id

line2: filter what is not exist in the map line2:过滤地图中不存在的内容

Set<String> mapId = entityResponse.getEntities().stream().map(Entity::getId).collect(Collectors.toSet());

List<String> entityNotExist = entityValues.stream().filter(n -> !mapId.contains(n.getId())).map(DTOEntity::getId).collect(Collectors.toList());

@DSchmdit answer worked for me. @DSchmdit 答案对我有用。 I would like to add on that.我想补充一点。 So my requirement was to filter a file based on some configurations stored in the table.所以我的要求是根据存储在表中的一些配置过滤文件。 The file is first retrieved and collected as list of dtos.该文件首先被检索并收集为 dtos 列表。 I receive the configurations from the db and store it as another list.我从数据库接收配置并将其存储为另一个列表。 This is how I made the filtering work with streams这就是我使用流进行过滤的方式

    List<FPRSDeferralModel> modelList = Files
            .lines(Paths.get("src/main/resources/rootFiles/XXXXX.txt")).parallel().parallel()
            .map(line -> {
                FileModel fileModel= new FileModel();
                line = line.trim();
                if (line != null && !line.isEmpty()) {
                    System.out.println("line" + line);
                    fileModel.setPlanId(Long.parseLong(line.substring(0, 5)));
                    fileModel.setDivisionList(line.substring(15, 30));
                    fileModel.setRegionList(line.substring(31, 50));
                    Map<String, String> newMap = new HashedMap<>();
                    newMap.put("other", line.substring(51, 80));
                    fileModel.setOtherDetailsMap(newMap);

                }
                return fileModel;
            }).collect(Collectors.toList());

    for (FileModel model : modelList) {
        System.out.println("model:" + model);
    }

    DbConfigModelList respList = populate();
    System.out.println("after populate");
    List<DbConfig> respModelList = respList.getFeedbackResponseList();


    Predicate<FileModel> somePre = s -> respModelList.stream().anyMatch(respitem -> {

        System.out.println("sinde respitem:"+respitem.getPrimaryConfig().getPlanId());
        System.out.println("s.getPlanid()"+s.getPlanId());
        System.out.println("s.getPlanId() == respitem.getPrimaryConfig().getPlanId():"+
        (s.getPlanId().compareTo(respitem.getPrimaryConfig().getPlanId())));
        return s.getPlanId().compareTo(respitem.getPrimaryConfig().getPlanId()) == 0
                && (s.getSsnId() != null);
    });



 final List<FileModel> finalList =  modelList.stream().parallel().filter(somePre).collect(Collectors.toList());

 finalList.stream().forEach(item -> {
     System.out.println("filtered item is:"+item);
 });

The details are in the implementation of filter predicates.细节在过滤谓词的实现中。 This proves much more perfomant over iterating over loops and filtering out这证明比循环迭代和过滤更高效

`List<String> unavailable = list1.stream()
                .filter(e -> (list2.stream()
                        .filter(d -> d.getStr().equals(e))
                        .count())<1)
                        .collect(Collectors.toList());`
for this if i change to 
`List<String> unavailable = list1.stream()
                .filter(e -> (list2.stream()
                        .filter(d -> d.getStr().equals(e))
                        .count())>0)
                        .collect(Collectors.toList());`
will it give me list1 matched with list2 right? 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM