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

时间:2015-04-07 11:23:39

标签: java filter

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

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

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

MyClass {

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

     String str;
     ...
     ...
}

我希望基于 - &gt;过滤掉字符串列表检查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);

现在我想要新的过滤列表 - &gt;它将具有值=&gt; “LMN”。即list2中不存在的元素,其元素位于list1

9 个答案:

答案 0 :(得分:16)

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

答案 1 :(得分:6)

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

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

答案 2 :(得分:5)

最后,我得到了以下方式实现这一目标 -

List<String> unavailable = list1.stream()
                .filter(e -> (list2.stream()
                        .filter(d -> d.getStr().equals(e))
                        .count())<1)
                        .collect(Collectors.toList());

但这也符合预期。 请告诉我这有效吗?如果有人有其他办法做同样的事情?

答案 3 :(得分:3)

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

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

接下来的问题是,您将在此流媒体操作结束时添加哪些代码,以便将结果进一步处理给您。

另外,list.contains非常慢,所以使用sets会更好。

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

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

鉴于我们不知道您将如何使用此功能,因此无法确定采用哪种方法。

答案 4 :(得分:2)

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

两个数组之间不常见:

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

答案 5 :(得分:1)

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

这可能会更有效。

答案 6 :(得分:0)

如果您的班级具有ID,并且您要按ID进行过滤

第1行:您映射了所有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());

答案 7 :(得分:0)

@DSchmdit答案对我有用。我想补充一点。因此,我的要求是根据表中存储的某些配置来过滤文件。 首先检索文件并将其收集为dto列表。我从数据库接收配置,并将其存储为另一个列表。这就是我如何对流进行过滤

{{1}}

详细信息在过滤谓词的实现中。事实证明,与遍历循环和过滤相比,性能更强

答案 8 :(得分:0)

`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?