本文目录导读:

在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 | 并行处理,大数据量快 | 不保证顺序 | 大数据量处理 |
选择哪种方法取决于你的具体需求:是否需要保持顺序、数据量大小、是否需要自定义比较规则等。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播