Java集合去重案例如何实现

wen java案例 32

本文目录导读:

Java集合去重案例如何实现

  1. List去重(保持顺序)
  2. 对象去重(自定义比较规则)
  3. 根据对象某个字段去重
  4. 性能优化:大数据量去重
  5. 综合示例:完整的工具类方法

在Java中,集合去重是一个非常常见的操作,根据不同的集合类型和具体需求,有多种实现方式,下面是几种常见的Java集合去重案例及实现方法。

List去重(保持顺序)

使用LinkedHashSet

import java.util.*;
public class ListDeduplicationExample {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 2, 3, 4, 4, 5, 1, 6);
        // 使用LinkedHashSet保持插入顺序
        Set<Integer> set = new LinkedHashSet<>(list);
        List<Integer> result = new ArrayList<>(set);
        System.out.println("原始列表: " + list);
        System.out.println("去重后列表: " + result);
    }
}

使用Stream API (Java 8+)

import java.util.*;
import java.util.stream.Collectors;
public class StreamDeduplicationExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("apple", "banana", "apple", "orange", "banana", "grape");
        // 使用Stream API去重
        List<String> result = list.stream()
                                .distinct()
                                .collect(Collectors.toList());
        System.out.println("原始列表: " + list);
        System.out.println("去重后列表: " + result);
    }
}

对象去重(自定义比较规则)

重写equals和hashCode

import java.util.*;
import java.util.stream.Collectors;
class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 重写equals方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }
    // 重写hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}
public class ObjectDeduplicationExample {
    public static void main(String[] args) {
        List<Person> persons = Arrays.asList(
            new Person("Alice", 25),
            new Person("Bob", 30),
            new Person("Alice", 25),  // 重复
            new Person("Charlie", 35),
            new Person("Bob", 30)     // 重复
        );
        // 使用Set去重(依赖equals和hashCode)
        Set<Person> personSet = new LinkedHashSet<>(persons);
        List<Person> result = new ArrayList<>(personSet);
        System.out.println("原始对象列表:");
        persons.forEach(System.out::println);
        System.out.println("\n去重后对象列表:");
        result.forEach(System.out::println);
    }
}

使用TreeSet自定义比较器

import java.util.*;
public class CustomComparatorDeduplicationExample {
    public static void main(String[] args) {
        List<Product> products = Arrays.asList(
            new Product("A001", "笔记本电脑", 5000),
            new Product("A002", "手机", 3000),
            new Product("A001", "笔记本电脑", 5000),  // 重复ID
            new Product("A003", "平板", 2000)
        );
        // 使用TreeSet根据产品ID去重
        Set<Product> productSet = new TreeSet<>((p1, p2) -> p1.getId().compareTo(p2.getId()));
        productSet.addAll(products);
        System.out.println("根据不同ID去重后的产品列表:");
        productSet.forEach(System.out::println);
    }
}
class Product {
    private String id;
    private String name;
    private double price;
    public Product(String id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }
    public String getId() { return id; }
    @Override
    public String toString() {
        return "Product{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", price=" + price + '}';
    }
}

根据对象某个字段去重

import java.util.*;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;
public class FieldDeduplicationExample {
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
            new Student(1, "张三", "A班"),
            new Student(2, "李四", "B班"),
            new Student(1, "张三", "C班"),  // 同一个学生,不同班级
            new Student(3, "王五", "A班"),
            new Student(2, "李四", "B班")   // 重复
        );
        // 方法1:根据学生ID去重,保留第一个出现的
        List<Student> result1 = students.stream()
            .collect(Collectors.collectingAndThen(
                Collectors.toMap(Student::getId, s -> s, (existing, replacement) -> existing),
                map -> new ArrayList<>(map.values())
            ));
        // 方法2:使用TreeSet
        Set<Student> set = new TreeSet<>(Comparator.comparing(Student::getId));
        set.addAll(students);
        List<Student> result2 = new ArrayList<>(set);
        System.out.println("根据ID去重后的学生列表(方法1):");
        result1.forEach(System.out::println);
        System.out.println("\n根据ID去重后的学生列表(方法2):");
        result2.forEach(System.out::println);
    }
}
class Student {
    private int id;
    private String name;
    private String className;
    public Student(int id, String name, String className) {
        this.id = id;
        this.name = name;
        this.className = className;
    }
    public int getId() { return id; }
    @Override
    public String toString() {
        return "Student{" + "id=" + id + ", name='" + name + '\'' + ", className='" + className + '\'' + '}';
    }
}

性能优化:大数据量去重

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class LargeDataDeduplicationExample {
    public static void main(String[] args) {
        // 模拟大数据量
        List<String> largeList = new ArrayList<>();
        for (int i = 0; i < 1000000; i++) {
            largeList.add("item_" + (i % 100000));  // 约10%重复
        }
        // 方法1:使用HashSet(快速,但不保持顺序)
        long startTime = System.currentTimeMillis();
        Set<String> set = new HashSet<>(largeList);
        List<String> result1 = new ArrayList<>(set);
        long endTime = System.currentTimeMillis();
        System.out.println("HashSet去重耗时: " + (endTime - startTime) + "ms");
        System.out.println("去重后数量: " + result1.size());
        // 方法2:使用Parallel Stream(并行处理)
        startTime = System.currentTimeMillis();
        List<String> result2 = largeList.parallelStream()
                                      .distinct()
                                      .collect(Collectors.toList());
        endTime = System.currentTimeMillis();
        System.out.println("Parallel Stream去重耗时: " + (endTime - startTime) + "ms");
        System.out.println("去重后数量: " + result2.size());
    }
}

综合示例:完整的工具类方法

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class DeduplicationUtil {
    // 1. List去重(保持顺序)
    public static <T> List<T> distinctList(List<T> list) {
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }
        return new ArrayList<>(new LinkedHashSet<>(list));
    }
    // 2. 根据对象字段去重
    public static <T, R> List<T> distinctByField(List<T> list, Function<? super T, ? extends R> keyExtractor) {
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }
        return list.stream()
            .filter(distinctByKey(keyExtractor))
            .collect(Collectors.toList());
    }
    // 辅助方法:根据key去重
    private static <T, R> Predicate<T> distinctByKey(Function<? super T, ? extends R> keyExtractor) {
        Set<R> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }
    // 3. 合并并去重两个列表
    public static <T> List<T> mergeAndDistinct(List<T> list1, List<T> list2) {
        Set<T> set = new LinkedHashSet<>();
        if (list1 != null) set.addAll(list1);
        if (list2 != null) set.addAll(list2);
        return new ArrayList<>(set);
    }
    public static void main(String[] args) {
        // 测试工具类
        List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 2, 3);
        List<Integer> list2 = Arrays.asList(3, 4, 5, 6, 1);
        System.out.println("原始列表1: " + list1);
        System.out.println("原始列表2: " + list2);
        System.out.println("去重后列表1: " + distinctList(list1));
        System.out.println("合并去重后: " + mergeAndDistinct(list1, list2));
    }
}
方法 优点 缺点 适用场景
LinkedHashSet 保持顺序,简单易用 需要重写equals/hashCode 普通的List去重
Stream distinct 代码简洁,支持链式操作 性能相对较低 Java 8+项目
TreeSet + Comparator 自定义排序,灵活 性能略低 需要自定义比较规则
HashMap去重 性能好,可自定义保留规则 代码较复杂 根据字段去重
Parallel Stream 并行处理,大数据量快 不保证顺序 大数据量处理

选择哪种方法取决于你的具体需求:是否需要保持顺序、数据量大小、是否需要自定义比较规则等。

抱歉,评论功能暂时关闭!