1. 概述
我们知道,在Java中,ArrayList
可以包含重复值。
在这篇简短教程中,我们将探讨从ArrayList
获取唯一值的几种方法。
2. 问题介绍
有时,我们需要从ArrayList
中提取唯一值——例如,为了增强数据分析、提高效率或简化进一步处理。假设我们有一个包含操作系统名称的列表:
List<String> MY_LIST = Arrays.asList(new String[]{
"Microsoft Windows",
"Mac OS",
"GNU Linux",
"Free BSD",
"GNU Linux",
"Mac OS"});
在上面的代码中,我们已经从数组初始化了MY_LIST
(/java-init-list-one-line#create-from-an-array)。目标是从MY_LIST
中获取唯一的操作系统名称列表。
我们将讨论两种不同的解决方法。为了简化,我们将使用单元测试(/java-unit-testing-best-practices)和AssertJ
断言来验证每种方法是否产生预期结果。
接下来,让我们看看如何操作。
3. 使用Set
消除重复元素
Set
和List
接口的一个重要区别是,Set
不能容纳重复元素。因此,要获取MY_LIST
的唯一元素,我们可以首先将MY_LIST
转换为Set
,**然后将Set
转换回List
**。
让我们创建一个测试来看看这如何工作:
List<String> result = new ArrayList<>(new HashSet<>(MY_LIST));
assertThat(result).containsExactlyInAnyOrder("Free BSD", "Microsoft Windows", "Mac OS", "GNU Linux");
细心的读者可能注意到我们使用了containsExactlyInAnyOrder()
方法进行验证。这是因为我们将MY_LIST
转换为了HashSet
,而**HashSet
不维护插入顺序**。
**如果需要保持插入顺序,我们可以将列表转换为LinkedHashSet
**:
result = new ArrayList<>(new LinkedHashSet<>(MY_LIST));
assertThat(result).containsExactly("Microsoft Windows", "Mac OS", "GNU Linux", "Free BSD");
正如我们所见,这次我们使用了containsExactly()
方法来验证结果。它不仅检查元素值,还检查它们的顺序。
4. 使用Stream API
Java 8引入的Stream API是其重要特性之一。它允许我们处理元素集合。
要从流中删除重复项,我们只需调用distinct()
方法:
List<String> result = MY_LIST.stream()
.distinct()
.collect(toList());
assertThat(result).containsExactly("Microsoft Windows", "Mac OS", "GNU Linux", "Free BSD");
运行测试时,它会通过。
值得一提的是,Collectors.toList()
始终保留流的原始顺序,除非我们将流转换为无序模式,例如通过调用unordered()
或使用Collectors.toSet()
将其转换为HashSet
。因此,我们使用containsExactly()
方法验证result
列表。
5. 总结
在Java开发中,从列表中获取唯一值是一个常见需求。在这篇文章中,我们深入探讨了解决这个问题的两种方法:
- 将
List
转换为Set
,然后将Set
再转换回List
- 使用Stream API的
distinct()
功能
通过详尽的示例,我们展示了这些技术如何有效地从列表中提取唯一元素。此外,我们还讨论了如何保持结果列表中元素的顺序,使其与原始输入列表保持一致。
如往常一样,这里展示的所有代码片段都在GitHub上可用。