【问题标题】:More efficient way to get the intersection between 2 or more nested ArrayLists [closed]获得 2 个或更多嵌套 ArrayLists 之间交集的更有效方法 [关闭]
【发布时间】:2021-05-15 23:40:11
【问题描述】:

如果我有,请说单独的 3 个嵌套的 ArrayLists 字符串,即 ArrayList<ArrayList<String>>

  1. 找到它们的交集(共同元素)的最有效方法是什么?
  2. 是否有其他数据结构可以替代嵌套的ArrayLists 结构,从而提高查找交集的效率? (例如,我能想到的第一个结构是使用Set,但我想看看是否有其他建议。)

提前致谢!

【问题讨论】:

  • 是的,你想要一套。任何一种套装都可以。 HashSet 通常可能会更快,而 TreeSet 的行为更可预测,并且在小尺寸时可能更快

标签: java list arraylist set-intersection


【解决方案1】:

两个列表的交集是使用retainAll() 方法完成的。

它会更新列表,所以如果你不想这样做,你应该先复制列表。

如果您有 2 个以上的列表,则复制第一个,然后为剩余的每个列表调用 retainAll()

ArrayList<ArrayList<String>> lists = ...

List<String> intersection = new ArrayList<>(lists.get(0));
for (List<String> list : lists.subList(1, lists.size()))
    intersection.retainAll(list);

但是性能会很差O(n*m),其中nm 是两个最大列表的大小。

这是因为retainAll() 对参数中给出的列表执行contains(),这是对intersection 列表中的每个元素的顺序搜索。

通过将列表转换为集合,性能可以提高到 O(n),其中n 是最大的列表。

List<String> intersection = new ArrayList<>(lists.get(0));
for (List<String> list : lists.subList(1, lists.size()))
    intersection.retainAll(new HashSet<>(list));

在 Java 8+ 中,for 循环可以简化为以下之一:

lists.subList(1, lists.size()).stream().map(HashSet::new).forEach(intersection::retainAll);

lists.subList(1, lists.size()).forEach(list -> intersection.retainAll(new HashSet<>(list)));

【讨论】:

    【解决方案2】:

    我会使用list.retainAll 方法

    private ArrayList<String> getIntersection(ArrayList<ArrayList<String>> lists) {
        if(null == lists || lists.isEmpty()) {
            return null;
        }
        ArrayList<String> intersection = lists.get(0);
        lists.forEach(intersection::retainAll);
        return intersection;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-28
      相关资源
      最近更新 更多