1. 引言

本文将介绍如何从List中移除重复元素的三种实现方式:
✅ 原生Java实现
✅ Guava工具库实现
✅ Java 8 Lambda表达式实现

本文属于"Java基础回顾"系列,面向有经验的开发者,基础概念将简略带过。

2. 使用原生Java移除重复元素

通过Java集合框架的Set特性可快速去重:

public void 
  givenListContainsDuplicates_whenRemovingDuplicatesWithPlainJava_thenCorrect() {
    List<Integer> listWithDuplicates = Lists.newArrayList(5, 0, 3, 1, 2, 3, 0, 0);
    List<Integer> listWithoutDuplicates = new ArrayList<>(
      new HashSet<>(listWithDuplicates));

    assertThat(listWithoutDuplicates, hasSize(5));
    assertThat(listWithoutDuplicates, containsInAnyOrder(5, 0, 3, 1, 2));
}

⚠️ 关键点

  • 原始List保持不变
  • 使用HashSet会导致元素顺序丢失(示例中顺序可能变为[0,1,2,3,5]

若需保留原始顺序,改用LinkedHashSet

public void 
  givenListContainsDuplicates_whenRemovingDuplicatesPreservingOrderWithPlainJava_thenCorrect() {
    List<Integer> listWithDuplicates = Lists.newArrayList(5, 0, 3, 1, 2, 3, 0, 0);
    List<Integer> listWithoutDuplicates = new ArrayList<>(
      new LinkedHashSet<>(listWithDuplicates));

    assertThat(listWithoutDuplicates, hasSize(5));
    assertThat(listWithoutDuplicates, containsInRelativeOrder(5, 0, 3, 1, 2));
}

3. 使用Guava移除重复元素

Guava提供更简洁的API实现相同功能:

public void 
  givenListContainsDuplicates_whenRemovingDuplicatesWithGuava_thenCorrect() {
    List<Integer> listWithDuplicates = Lists.newArrayList(5, 0, 3, 1, 2, 3, 0, 0);
    List<Integer> listWithoutDuplicates 
      = Lists.newArrayList(Sets.newHashSet(listWithDuplicates));

    assertThat(listWithoutDuplicates, hasSize(5));
    assertThat(listWithoutDuplicates, containsInAnyOrder(5, 0, 3, 1, 2));
}

注意

  • 默认使用HashSet,顺序不保证
  • 需保留顺序时改用Sets.newLinkedHashSet()
public void 
  givenListContainsDuplicates_whenRemovingDuplicatesPreservingOrderWithGuava_thenCorrect() {
    List<Integer> listWithDuplicates = Lists.newArrayList(5, 0, 3, 1, 2, 3, 0, 0);
    List<Integer> listWithoutDuplicates 
      = Lists.newArrayList(Sets.newLinkedHashSet(listWithDuplicates));

    assertThat(listWithoutDuplicates, hasSize(5));
    assertThat(listWithoutDuplicates, containsInRelativeOrder(5, 0, 3, 1, 2));
}

4. 使用Java 8 Lambda移除重复元素

Java 8的Stream API提供最优雅的解决方案

public void 
  givenListContainsDuplicates_whenRemovingDuplicatesWithJava8_thenCorrect() {
    List<Integer> listWithDuplicates = Lists.newArrayList(5, 0, 3, 1, 2, 3, 0, 0);
    List<Integer> listWithoutDuplicates = listWithDuplicates.stream()
     .distinct()
     .collect(Collectors.toList());

    assertThat(listWithoutDuplicates, hasSize(5));
    assertThat(listWithoutDuplicates, containsInAnyOrder(5, 0, 3, 1, 2));
}

核心优势

  • distinct()方法自动保留首次出现的元素顺序
  • 代码简洁,链式调用可读性强
  • 底层基于equals()方法判断重复

5. 总结

三种方案对比:

实现方式 代码简洁度 顺序保留 性能 适用场景
原生Java ⭐⭐ 可选 O(n) 无依赖环境
Guava ⭐⭐⭐ 可选 O(n) 已引入Guava项目
Java 8 Stream ⭐⭐⭐⭐ O(n) Java 8+环境

所有示例代码可在GitHub项目获取,Maven项目可直接导入运行。

踩坑提醒

  • 使用HashSet去重时,务必确认元素是否已实现hashCode()equals()
  • 大数据量场景下,distinct()的内存消耗需关注(底层使用LinkedHashSet

原始标题:Removing All Duplicates From a List in Java Baeldung

« 上一篇: Java 学习指南
» 下一篇: Baeldung周报23