当前位置:  开发笔记 > 编程语言 > 正文

使用java 8 stream在2个列表中查找元素匹配

如何解决《使用java8stream在2个列表中查找元素匹配》经验,为你挑选了2个好方法。

我的情况是:

class Person {
    String id ;
    String name;
    String age;
}
List list1 = {p1,p2, p3};
List list2 = {p4,p5, p6}; 

我想知道是否有人list1有相同的名字和年龄,list2但不介意id.

什么是最好和最快的方式?



1> Tunaki..:

一个简单的方法是覆盖equalshashCode.由于我假设之间的平等Person,还必须考虑的id领域,你可以用这个例子为PersonWrapper将实施正确的equalshashCode(即只检查nameage字段):

class PersonWrapper {

    private Person person;

    private PersonWrapper(Person person) {
        this.person = person;
    }

    public static PersonWrapper wrap(Person person) {
        return new PersonWrapper(person);
    }

    public Person unwrap() {
        return person;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        PersonWrapper other = (PersonWrapper) obj;
        return person.name.equals(other.person.name) && person.age.equals(other.person.age);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + person.name.hashCode();
        result = prime * result + person.age.hashCode();
        return result;
    }

}

有了这样的课程,您就可以拥有以下内容:

Set set2 = list2.stream().map(PersonWrapper::wrap).collect(toSet());

boolean exists =
    list1.stream()
         .map(PersonWrapper::wrap)
         .filter(set2::contains)
         .findFirst()
         .isPresent();

System.out.println(exists);

此代码将其list2转换Set为包装人员.拥有a的目标Set是进行恒定时间contains操作以获得更好的性能.

然后,list1过滤.找到的每个元素都set2被保留,如果剩下一个元素(也就是说,如果findFirst()返回非空Optional元素),则表示找到了一个元素.


@TodorNeykov这就是我猜的,我用`equals`实现了一个自定义类,看看我的回答.

2> Holger..:

为自己定义一个关键对象,该对象可以保存并比较所需的属性。在这种简单情况下,您可以使用一个小的列表,而每个索引对应一个属性。对于更复杂的情况,可以使用Map(使用属性名称作为键)或专用类:

Function> toKey=p -> Arrays.asList(p.getName(), p.getAge());

具有这种映射功能。您可以使用简单的解决方案:

list1.stream().map(toKey)
     .flatMap(key -> list2.stream().map(toKey).filter(key::equals))
     .forEach(key -> System.out.println("{name="+key.get(0)+", age="+key.get(1)+"}"));

如果您的列表很大,可能会导致性能不佳。如果列表较大(或无法预测其大小),则应使用中间变量Set来加速查找(将任务的时间复杂度从更改O(n²)O(n)):

list2.stream().map(toKey)
     .filter(list1.stream().map(toKey).collect(Collectors.toSet())::contains)
     .forEach(key -> System.out.println("{name="+key.get(0)+", age="+key.get(1)+"}"));

在上面的示例中,每个匹配项都被打印出来。如果您仅对是否存在这样的匹配感兴趣,则可以使用以下任一方法:

boolean exists=list1.stream().map(toKey)
     .anyMatch(key -> list2.stream().map(toKey).anyMatch(key::equals));

要么

boolean exists=list2.stream().map(toKey)
     .anyMatch(list1.stream().map(toKey).collect(Collectors.toSet())::contains);

推荐阅读
牛尾巴2010
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有