【问题标题】:Compare large lists and extract missing data比较大型列表并提取缺失数据
【发布时间】:2018-09-28 15:33:50
【问题描述】:

我有两个非常大的ArrayList,每个都包含数百万个数据。我想从List1 中过滤掉List2 中不存在的数据和/或反之亦然。

我尝试了 Apache CollectionUtils,Java 8 流 API 没有任何成功。

Java 8 并行流正在消耗所有 CPU,CollectionUtils 继续比较数据集而没有任何输出。

POJO 示例

public DataVO {
 private String id;
 private String value;
 ...
 // getters / setters

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = (prime * result) + ((id == null) ? 0 : id.hashCode());
  return result;
 }

 @Override
 public boolean equals(final Object obj) {
  ...
  ...
  final DataVO other = (DataVO) obj;
  if (id == null) {
   if (other.id != null) {
    return false;
   }
  }
  else if (!id.equals(other.id)) {
   return false;
  }
  return true;
 }
}

hashCode() / equals() 可以有更多字段,现在我保持简单。

我还尝试将List1 拆分为更小的块,然后尝试与List2 进行比较,但没有任何结果。我查看了其他问题,但没有一个问题考虑过大容量。

如果您有任何指示,请告诉我。

【问题讨论】:

  • 如果您要交叉比较列表中的数百万个项目,则需要时间和内存。您可能需要进行一些完整性检查日志记录(例如,每 100k 打印一次当前项目的索引或其他内容),以便您至少可以看到(a)它正在取得任何进展,以及(b)它是否/在哪里陷入困境或者仅仅是因为您必须多次迭代多个列表。一般来说,你不想这样做。
  • 您是否尝试将第一个数组放入集合,然后遍历第二个集合并检查元素是否在集合中?
  • 您需要了解集合的运行时复杂性。在 List 中查找对象是 O(N) ,使得整个过程 O(M*N)。在 HashSet 中找到一个对象是 O(1)。因此,将其中一个列表(最小的一个)变成一个 HashSet,检查另一个列表的元素是否存在于 Set 中。这将使过程 O(M)。
  • 这些数组是否已排序?如果是,我们将使用类似于“合并排序”的算法来解决问题。
  • 感谢大家的反馈。我需要提取丢失的数据,顺序无关紧要。如果 list1=[1,2,3,4] 和 list2=[4,3,5,6] 那么输出应该是 list=[1,2]。由于大小,Apache CollectionUtils substractremoveAll 都不起作用。我会试试HashSet,希望能奏效。

标签: java list collections


【解决方案1】:

您可以将ArrayList 的大块读入HashSet,例如10k 个元素。确保在 HashSet 构造函数上设置大小。然后对于每个块调用HashSet#RemoveAll 和另一个ArrayList。其余条目是您的答案。甚至可能与 ThreadPoolExecutor 并行。

List missing = new ArrayList(); // answer

for (int i = 0; i < list1.size(); ) {
    int offset = i;
    i += 16 * 1024;
    if (i > list1.size()) i = list1.size();
    Set chunk = new HashSet(list1.subList(offset, i));

    for (int j = list2.size(); --j >= 0; chunk.remove(list2.get(j));
    missing.addAll(chunk);
}

【讨论】:

  • 感谢您的解决方案。它符合我的要求。
  • 我在外部修改了一些创建sub lists,但其余逻辑保持不变。
  • @TechSawi 您所说的“外部”是什么意思?请注意,每次循环迭代中确切的子列表都会发生变化...
  • @Marco13 我分别创建了子列表,它们循环遍历列表以查找丢失的数据。所用时间减半。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 2016-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多