You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中基于姓名属性匹配,按对应数量移除列表元素

问题解决:高效移除List中匹配姓名的首个元素

原代码问题分析

你的代码存在两个核心问题:

  • 过滤条件错误:person.firstName = p.firstName是赋值操作,不是字符串比较,正确写法应为person.firstName.equals(p.firstName)
  • 效率与并发问题:每次遍历people2都对people1做全量线性扫描,时间复杂度为O(n*m);同时直接在Stream操作中调用people1.remove(person)会触发ConcurrentModificationException(ArrayList迭代器为快速失败机制)

高效实现方案

方案1:基于姓名频率统计+构建新列表(最优,时间复杂度O(n+m))

先统计people2中每个姓名的出现次数,再遍历people1,仅保留超出对应姓名移除次数的元素:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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

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

    // 重写toString方便打印结果
    @Override
    public String toString() {
        return firstName + ", " + age;
    }

    public String getFirstName() {
        return firstName;
    }
}

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<>();
        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<>();
        people2.add(p6);
        people2.add(p7);
        people2.add(p8);

        // 统计people2中每个姓名需要移除的次数
        Map<String, Long> nameRemoveCount = people2.stream()
                .map(Person::getFirstName)
                .collect(Collectors.groupingBy(name -> name, Collectors.counting()));

        List<Person> result = new ArrayList<>();
        for (Person person : people1) {
            String name = person.getFirstName();
            // 如果该姓名还有需要移除的次数,跳过当前元素(即移除),否则加入结果列表
            if (nameRemoveCount.containsKey(name) && nameRemoveCount.get(name) > 0) {
                nameRemoveCount.put(name, nameRemoveCount.get(name) - 1);
            } else {
                result.add(person);
            }
        }

        // 替换原列表(如需保留原列表引用)
        people1.clear();
        people1.addAll(result);

        System.out.println(people1); // 输出: [John, 61, John, 13]
    }
}

方案2:迭代器遍历移除(适合小列表,时间复杂度O(n*m))

如果列表规模不大,可直接用迭代器遍历people1,找到首个匹配姓名的元素并移除:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        // 初始化代码同方案1...

        for (Person p : people2) {
            Iterator<Person> iterator = people1.iterator();
            while (iterator.hasNext()) {
                Person person = iterator.next();
                if (person.getFirstName().equals(p.getFirstName())) {
                    iterator.remove(); // 用迭代器移除,避免并发修改异常
                    break; // 仅移除第一个匹配项,跳出循环
                }
            }
        }

        System.out.println(people1); // 输出: [John, 61, John, 13]
    }
}

方案对比

  • 方案1:时间复杂度O(n+m),通过一次统计+一次遍历完成,效率最高,适合大列表场景
  • 方案2:时间复杂度O(n*m),实现简单直观,适合数据量较小的场景

内容的提问来源于stack exchange,提问作者Sherbet Head

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 07:42:57