我有来自同一类的两个列表(例如,具有名称和年龄属性的 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
列表中存在同名的人,则找到第一个匹配项并将其删除(只关心名字,而不关心年龄)。
期望的结果:包含
的列表您遇到的主要效率问题是 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());