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

iterating and filtering two lists using java 8

我想迭代两个列表并获得新的过滤列表,该列表将包含第二个列表中不存在的值。有人可以帮忙吗?

我有两个列表 - 一个是字符串列表,另一个是 MyClass 个对象列表。

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

MyClass {

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

     String str;
     ...
     ...
}

我想过滤字符串列表基于 -> 检查第二个列表中的元素 (abc),其值不在 list1.

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

现在我想要新的筛选列表 -> 将具有值 => "lmn"。即 list2 中不存在的值,其元素在 list1.

如果您流式传输第一个列表并使用基于包含在第二个列表中的过滤器...

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

下一个问题是您将在此流操作的末尾添加什么代码以进一步处理结果……交给您了。

此外,list.contains速度很慢,所以你最好用集合。

但是如果你使用集合,你可能会发现一些更简单的操作来处理这个问题,比如 removeAll

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

鉴于我们不知道您将如何使用它,所以不太可能建议采用哪种方法。

这可以通过以下方式实现...

 List<String> unavailable = list1.stream()
                            .filter(e -> !list2.contains(e))
                            .collect(Collectors.toList());
// 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());

见下文,欢迎任何人对以下代码提出反馈意见。

两个数组之间不常见:

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

两个数组之间的共同点:

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

使用流进行操作简单易读:

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

这可能会更有效率。

如果您有 class 的 ID 并且您想按 ID

过滤

line1 : 你映射了所有的 id

第 2 行:过滤地图中不存在的内容

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 的回答对我有用。我想补充一点。所以我的要求是根据 table 中存储的一些配置来过滤文件。 该文件首先被检索并收集为 dto 列表。我从数据库接收配置并将其存储为另一个列表。这就是我使用 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);
 });

详情在过滤谓词的实现中。这证明比遍历循环和过滤掉

更有效
`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?