从大文件创建地图

时间:2014-08-19 15:14:35

标签: java map mapdb

我有一个非常大的文件(10 ^ 8行),其事件计数如下,

A 10
B 11
C 23
A 11

我需要累积每个事件的计数,以便我的地图包含

A 21
B 11
C 23

我目前的做法:

读取线条,维护地图,并按地址更新地图中的计数

updateCount(Map<String, Long> countMap, String key,
            Long c) {
        if (countMap.containsKey(key)) {
            Long val = countMap.get(key);
            countMap.put(key, val + c);
        } else {
            countMap.put(key, c);
        }
    }

目前这是代码中最慢的部分(大约需要25毫秒)。 请注意,该地图是基于MapDB的,但我怀疑这些更新是否很慢(是吗?)

这是地图的mapdb配置,

DBMaker.newFileDB(dbFile).freeSpaceReclaimQ(3)
                .mmapFileEnablePartial()
                .transactionDisable()
                .cacheLRUEnable()
                .closeOnJvmShutdown();

有办法加快速度吗?

修改

唯一键的数量是维基百科中页面的顺序。这些数据实际上是来自here的网页流量数据。

3 个答案:

答案 0 :(得分:0)

您可以尝试

class Counter {
    long count;
}

void updateCount(Map<String, Counter> countMap, String key, int c) {
    Counter counter = countMap.get(key);
    if (counter == null) {
        counter = new Counter();
        countMap.put(key, counter);
        counter.count = c;
    } else {
        counter.count += c;
    }
}

这不会创建很多Long包装器,而只是为计数器分配键数。

注意:不要创建Long。上面我使c成为一个int,不监督long / Long。

答案 1 :(得分:0)

作为一个起点,我建议考虑:

  • 您所说的25毫秒对于所涉及的数据量和通用地图实施来说实际上是不合理的时间量是什么标准?如果你量化它,它可能会帮助你解决是否有任何错误。
  • 对地图进行重新散列所花费的时间与其他操作相比(例如,每次放置时计算哈希码)?
  • 您的活动&#34;你称之为?有多少独特的事件 - 因此有独特的键 - ?如何生成地图的键,是否有更有效的方法呢? (例如,在标准哈希映射中,您为每个关联创建其他对象,并实际存储关键对象,从而增加内存占用量。)
  • 根据前一个问题的答案,您可以自己推出更有效的地图结构(请参阅this example您可以调整的内容)。从本质上讲,您需要在花费时间的情况下看具体(例如,每次放置的哈希码计算/重新散列的成本)并尝试优化该部分。

答案 2 :(得分:0)

如果您使用的是TreeMap,则可以使用

等性能调整选项
  1. 每个节点中的条目数。
  2. 您还可以使用特定的键和值序列化程序来加速序列化和去除化。
  3. 您可以使用Pump模式构建树,这非常快。但有一点需要注意的是,当您从头开始构建新地图时,这非常有用。你可以在这里找到完整的例子
  4. https://github.com/jankotek/MapDB/blob/master/src/test/java/examples/Huge_Insert.java