【问题标题】:Efficient way how to check differences between two collections in Java如何在Java中检查两个集合之间的差异的有效方法
【发布时间】:2015-09-22 10:45:35
【问题描述】:

我有一个List 的字符串{1,2,7}

现在我有了一个新的List{2,4,9}

规则很简单:

  1. 如果列表 A 中的元素在列表 B 中不存在,我们将其添加到新的删除列表中
  2. 如果列表 B 中的元素在列表 A 中不存在,我们将其添加到新的创建列表中
  3. 如果元素在两个列表中都存在,我们不会触及它

所以结果是两个新列表:

删除列表:{1,7}

创建列表:{4,9}

知道如何在 java 中提高效率吗?也许使用 Java8 更容易?

我的列表有大约 1000 个元素。

【问题讨论】:

  • 元素存储在ArrayList还是Array中?
  • 你可以选择..只要达到目的无所谓。
  • 如果顺序不重要,使用Set操作,如addAll()deleteAll()retainAll()
  • 同意萨沙。使用 set 会更有意义。
  • 我编辑了这个问题。你能回答一下吗?

标签: java collections lambda


【解决方案1】:

如果排序不重要,请使用Set 批量操作:

Set<String> a = new HashSet<>(Arrays.asList("1", "2", "7"));
Set<String> b = new HashSet<>(Arrays.asList("2", "4", "9"));

Set<String> deleteSet = new HashSet<>(a);
deleteSet.removeAll(b);                   // [1, 7]
Set<String> createSet = new HashSet<>(b);
createSet.removeAll(a);                   // [4, 9]

如果你想要 Java 8,只需过滤元素并收集:

List<String> deleteList = a.stream().filter(e -> !b.contains(e)).collect(Collectors.toList());
List<String> createList = b.stream().filter(e -> !a.contains(e)).collect(Collectors.toList());

这里,ab 可以是列表,但强烈建议将它们设为 Sets,因为在大多数列表实现中,contains() 的操作是 O(n)。

【讨论】:

  • 没有这样的方法 deleteAll 你的意思是 removeAll 吗?
  • @SashaSalauyou:您似乎缺少进口。
  • @SashaSalauyou 如果我的集合元素不是字符串而是一个包含我想与之比较的原语的对象怎么办
  • @rayman 如果您使用自定义类,请覆盖其hashCode()equals() 以遵循合同docs.oracle.com/javase/7/docs/api/java/lang/…
  • @rayman 那么我最好并行化调用,而不是流处理......无论如何,如果没有测试,没有人会明确地说什么更好。
【解决方案2】:
delete_list = A.copy();
create_list = B.copy();
delete_list.stream().removeIf(e -> B.contains(e));
create_list.stream().removeIf(e -> A.contains(e));

基本上我们只是创建两个不同的列表。在集合论中,我们可以这样写输出:

delete_list = A \ B
create_list = B \ A

感谢@SashaSalauyou 提醒我注意我犯的一个错误。

【讨论】:

  • 对不起,我错过了一些重要的要求,我编辑了我的问题,请再看一遍
  • 在第 4 行什么都不会发生,因为在第 3 行你从集合 A 中删除了所有常见元素。
  • @SashaSalauyou 哦,是的。谢谢,应该注意到了。我会编辑
【解决方案3】:

虽然不是很优雅的解决方案,但我们也可以在 Java8 中使用Streams

Set<String> setOne = new HashSet<>(Arrays.asList("1","2","7"));
Set<String> setTwo = new HashSet<>(Arrays.asList("2","4","9"));
System.out.println(setOne.stream().filter(i-> !setTwo.contains(i)).collect(Collectors.toList()));
System.out.println(setTwo.stream().filter(i-> !setOne.contains(i)).collect(Collectors.toList()));

打印出来:

[1, 7] [4, 9]

有一点很重要,setOnesetTwo 应该是有效的 final 才能在 lambda 表达式中工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-05
    • 2014-01-16
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 2010-11-24
    相关资源
    最近更新 更多