Java 从一个 List 中删除重复的元素

概述

本文章主要为了帮助你了解如何在 Java 的 List 中快速清除掉重复的元素。

我们将会使用下面的 3 种方法来进行演示:

  • 纯 Java
  • Guava
  • Java 8 Lambda 表达式

在 Java 中删除 List 中重复元素的主要思路就是将 List 转换为 Set。

因为 Set 中是不允许重复元素的,那这样就可以完成重复元素的删除了。

使用纯 Java 来删除 List 中的重复元素

我们可以使用 Java 的标准 集合(Collections)来完成操作。

List 和 Set 都是属于 集合(Collections)中的一种。

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

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

考察上面的代码,上面的代码我们使用了 HashSet 来包装的实现,并且重新返回了 ArrayList。

同时我们注意到,上面的代码会保持需要处理的 List 中的内容不变。

有关顺序的问题,因为我们知道 HashSet 中的元素是无序的,正是因为这个特性,那么我们转换成功后的 List 数据有可能和输入的 List 数据的顺序不一致。

因为无序的关系,List 中的 Hash 值可能在重新计算后不一样。

如果我们希望将 List 中重复数据删除后的 List 数据和原始输入 List 数据的排序一致的话,我们可以使用 LinkedHashSet 来替代 HashSet

请考察下面的代码:

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

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

上面的代码在将重复删除后还是会保持顺序不变的。

使用 Guava 删除重复元素

我们可以使用 Guava 完成上面一样的操作:

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

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

上面我们使用的是 Guava 的代码。

在这个代码中我们使用了 Sets,Sets 是 Guava 使用的一个类,然后用这个类的 newHashSet 来实现包装。

同样的,如果希望顺序保持不变的话,你需要使用 LinkedHashSet 的实现才可以。

    @Test
    public void givenListContainsDuplicates_whenRemovingDuplicatesPreservingOrderWithGuava_thenCorrect() {
        final List<Integer> listWithDuplicates = Lists.newArrayList(5, 0, 3, 1, 2, 3, 0, 0);
        final List<Integer> listWithoutDuplicates = Lists.newArrayList(Sets.newLinkedHashSet(listWithDuplicates));

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

上面的代码将会保持清理后的 List 中元素的顺序不变。

使用 Java 8 Lambdas 表达式

现在,我们来开始使用 Java 8 Lambdas 表达式的实现方式。

在这个实现中,我们使用 Stream API 的 distinct() 方法,这个方法将会返回一个 stream ,这个 stream 将会 distinct 元素。

另外,针对这种删除方式的处理中的元素是稳定的,意思是在删除重复的时候元素的排序是按照这个元素第一次出现的位置来保持顺序的。

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

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

上面就是我们在实际上可能会使用将 List 中重复元素进行删除所使用的一些方法。

结论

在本文中,我们对 List 中的 重复对象如何删除进行了一些探讨。

通过上面的一些方法能够让你在 Java 进行编程的时候快速删除 List 中的重复元素。

测试源代码

相关的测试源代码,请访问链接:

您也可以 Fork 代码后提交更新。