通过比较键值返回两个列表之间的差异,而不是Java中的整个对象

问题描述 投票:0回答:1

我有来自同一类的两个列表(例如,具有名称和年龄属性的 Person 类),并且我试图想出一种有效的方法来从列表 A 中删除元素(如果它们出现在列表 B 中),但前提是name 属性匹配(忽略年龄)。我不想从列表 B 中删除具有匹配名称的所有值,而是从列表 A 中为列表 B 中的每个匹配名称删除一个值。

这是一个例子:

public class Person {
    private String firstName;
    private Integer age;

    public Person(String firstName, Integer age) {
        this.firstName = firstName;
        this.age = age;
    }
}

public class Main {
    public static void main(String[] args) {

        Person p1 = new Person("John", 25);
        Person p2 = new Person("Lisa", 54);
        Person p3 = new Person("Mike", 61);
        Person p4 = new Person("John", 61);
        Person p5 = new Person("John", 13);
        List<Person> people1 = new ArrayList<Person>();
        people1.add(p1);
        people1.add(p2);
        people1.add(p3);
        people1.add(p4);
        people1.add(p5);

        Person p6 = new Person("John", 88);
        Person p7 = new Person("Lisa", 66);
        Person p8 = new Person("Mike", 71);
        List<Person> people2 = new ArrayList<Person>();
        people2.add(p6);
        people2.add(p7);
        people2.add(p8);


        for (Person p : people2) {
            people1.stream()
                .filter(person -> Boolean.parseBoolean(person.firstName = p.firstName))
                .findFirst()
                .ifPresent(person -> people1.remove(person));
        } // This is what i've tried, but it doesn't work and seems very inefficient

        System.out.println(people1);
    }

基本上,我想遍历

people2
列表,如果
people1
列表中存在同名的人,则找到第一个匹配项并将其删除(只关心名字,而不关心年龄)。

期望的结果:包含

的列表
  • 约翰,61 岁
  • 约翰,13 岁
java loops filter java-stream
1个回答
0
投票

您遇到的主要效率问题是 2 个循环,一个循环嵌套在另一个循环中,导致时间复杂度为 O(n2)。

但是,您可以通过使用更有效的方法从

people1
中找到匹配的人来实现 O(n) 时间复杂度:


Map<String, List<Person>> map = people1.stream().collect(Collectors.groupingBy(Person::getFirstName));
for (Person p : people2) {
    Optional.ofNullable(map.getOrDefault(p.getFirstName(), null))
      .filter(list -> !list.isEmpty())
      .ifPresent(list -> list.remove(0));
}
people1 = map.values().stream().flatMap(List::stream).collect(Collectors.toList());
© www.soinside.com 2019 - 2024. All rights reserved.