【问题标题】:count distinct values in big long array (performance issue)计算大长数组中的不同值(性能问题)
【发布时间】:2016-01-08 23:35:48
【问题描述】:

我有这个:

long hnds[] = new long[133784560]; // 133 million

然后我快速填充数组(几毫秒),然后我想知道唯一(即不同)值的数量。现在,我什至不需要这个实时,我只需要尝试几个变体,看看每个变体有多少唯一值。

我试过了,例如这个:

import org.apache.commons.lang3.ArrayUtils;
....
HashSet<Long> length = new HashSet<Long>(Arrays.asList(ArrayUtils.toObject(hnds)));
System.out.println("size: " + length.size());

等待半小时后出现堆空间错误(我有 Xmx4000m)。

我也尝试初始化 Long[] hnds 而不是 long[] hnds,但是数组的初始填充需要很长时间。或者例如在添加值时从一开始就使用 Set ,但它也需要永远。有没有办法计算 long[] 数组的不同值而无需永远等待?如果必须的话,我会以某种方式将其写入文件。

【问题讨论】:

    标签: java performance hashset


    【解决方案1】:

    我最好的建议是使用 fastutil (http://fastutil.di.unimi.it/) 之类的库,然后使用自定义未装箱哈希集:

    import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
    System.out.println(new LongOpenHashSet(hnds).size());
    

    (另外,顺便说一句,如果您可以接受近似答案,您可以尝试更多更有效的算法;详情请参阅例如this paper。)

    【讨论】:

    • 哇哦!我仍然需要稍微增加内存,但它会在几秒钟内运行!我也可以用它来做其他事情!
    【解决方案2】:

    只需对其进行排序和计数。

     int sz = 133784560;
     Random randy = new Random();
     long[] longs = new long[sz];
     for(int i = 0; i < sz; i++) { longs[i] = randy.nextInt(10000000); }
     Arrays.sort(longs);
     long lastSeen = longs[0];
     long count = 0;
     for(int i = 1; i < sz; i++) {
       if(longs[i] != lastSeen) count++;
       lastSeen = longs[i];
     }
    

    在我的笔记本电脑上大约需要 15 秒。

    【讨论】:

      猜你喜欢
      • 2017-11-09
      • 1970-01-01
      • 1970-01-01
      • 2014-01-23
      • 1970-01-01
      • 2012-04-20
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多