从两个列表中删除重复项。

3

我有两个字符串列表,要去除重复项可以这样做:

List<String> list1 = Arrays.asList("1", "2", "3", "4");
List<String> list2 = Arrays.asList("1", "4", "5", "6");
List<String> duplicates = list1.stream().filter(s -> list2.contains(s)).collect(Collectors.toList());
list1.removeAll(duplicates);
list2.removeAll(duplicates);

因此,结果为:
list1 = 2, 3
list2 = 5, 6

有没有更好的方法来完成这个任务?比如说,用更少的语句。

3
哪方面更好呢?是减少比较,还是减少内存消耗? - luk2302
定义“更好”的含义。如果您指的是“渐近时间复杂度”,那么您可以通过使用哈希集来实现更好的效果。 - Oliver Charlesworth
"更好" 可以是主观的。小心你要问什么。 - Jacob B.
你想删除重复项,即只保留唯一的项目,还是想要两个集合的差异?现在你正在删除两个列表中都出现的所有项目。对于前者,只需使用Set。对于后者,这看起来不错。 - Mzzl
从两个列表中删除重复项。感谢@OliverCharlesworth提供使用HashSet的提示。 - Packs
2个回答

1
你可以使用在Collection接口中定义的removeAll方法。

boolean removeAll(Collection<?> c)

删除此集合中与指定集合相同的所有元素(可选操作)。调用此方法后,此集合将不包含与指定集合共有的任何元素。

// init
List<String> sourceList1 = Arrays.asList("1", "2", "3", "4");
List<String> sourceList2 = Arrays.asList("1", "4", "5", "6");

// you need to create duplicate collection, because removeAll modify collection 
List<String> resultList1 = new ArrayList(sourceList1);
List<String> resultList2 = new ArrayList(sourceList2);

//remove duplicates from collections
resultList1.removeAll(sourceList2); // second from first
resultList2.removeAll(sourceList1); // first from second


0

值得考虑的一种可能性是创建Set<String>并将这些列表添加到其中。集合只允许向其自身添加唯一值,它可以防止添加重复内容。

使用Set的第一种方式:创建一个包含两个列表交集的Set。当你检查源对象的每个项都不存在于先前创建的Set中时,才进行新列表的添加和去重。

第二种方法(仅当你的列表本身不关心重复内容时 - 例如,在第一个列表中存在两次相同的值):为第一个列表和第二个列表创建一个Set,并将这些列表添加到其中,然后检查是否存在重复内容。

正如我在评论中提到的那样,我可能误解了问题,并寻找“另一种”而不是“更有效”的方法来实现您所要求的内容,但可能仍然有所帮助。


请解释在这种情况下如何工作。OP想要完全删除重复项,而不是最多只保留一个值。 - luk2302
我可能会有些误解,这可能不是实现它的最有效方式,所以很抱歉错过了提供“更有效的方法”的部分。第一和第二个列表可以检查与此集合的共同部分,并将结果存储在新列表中。再次,非常抱歉,我误解了它并想提供另一种方式,而不是最有效的方式。 - Przemysław Moskal
我不是在谈论“高效”的部分。我不明白你如何使用Set来尝试从两个数组中删除重复的值。 - luk2302
@luk2302 - 将列表转换为集合可以将预期运行时间(对于交集逻辑)从O(n^2)降至O(n)。 - Oliver Charlesworth
@OliverCharlesworth 我明白了,一开始就使用Set是可行的。 - luk2302
我更新了我的答案,让你知道我在写关于集合的意思。 - Przemysław Moskal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接