迭代时比较HashMap元素的优化

时间:2017-01-06 22:24:52

标签: java hashmap iteration similarity concurrenthashmap

我有一个名称接近845k行的csv文件。

我想比较模糊名称字符串匹配。 我使用了着名的Python模糊算法的Java fuzzy string matching实现。

在下面的代码中实现它对我来说非常适合。 问题是处理时间太长。 每条线与其他线的比较时间接近15秒。 这是240线一小时,整个过程将近6000行。 所有流程都将在几个月内完成。 这是不可接受的工作时间。

我需要一种优化技术或方法。 我需要一些建议而不是解决方案。

您对以下代码的建议是什么?

BufferedReader br = new BufferedReader(new FileReader("data/names.csv"));
BufferedWriter bw = new BufferedWriter(new FileWriter("data/similars.csv"));
ConcurrentHashMap<Integer,String> map = new ConcurrentHashMap<Integer,String>();

String lines;
while( (lines = br.readLine()) != null ){
    String[] line = lines.split("\\t",-1);
    Integer nameId = Integer.parseInt(line[0]);
    String name = line[1];
    map.put(nameId, name);
}

for (Map.Entry<Integer, String> entry1 : map.entrySet()) {
    Integer nameId1 = entry1.getKey();
    String name1 = entry1.getValue();

    for (Map.Entry<Integer, String> entry2 : map.entrySet()) {
        Integer nameId2 = entry2.getKey();
        if (nameId1 == nameId2) {
            continue;
        }
        String name2 = entry2.getValue();
        int ratio = FuzzySearch.ratio(name1,name2);
        if(ratio > 95){
            bw.write(nameId1 + "," + nameId2 + "\n");
        }
    }
    // For to prevent matching same pairs again 
    map.remove(nameId1);
}

1 个答案:

答案 0 :(得分:3)

  1. 您可以尝试使用Levenshtein距离算法,也许它会为您提供更好的性能。或尝试任何其他算法。提供algoritm实施的链接
  2. 最好不要将Integer与==进行比较,使用nameId1.intValue() == nameId2
  3. 创建N个线程,其中N是核心数。将所有行放在ConcurrentLinkedQueue中。让你的线程轮询队列,一句话,做一个同情,一旦完成 - 写入同步部分下的文件。它允许您在PC上使用所有核心,而不仅仅是1
  4. 为什么需要这么多时间,也许你有一些内存限制,这会迫使GC吃掉你的CPU周期并影响性能。
  5. 你可以应用一些小的优化,假设如果单词长度之间的差异超过50%,你永远不会得到95%匹配
  6. 看看他们正在使用阈值的implementation ,我相信它会给你最大提升,我认为如果距离大于阈值,算法会提前返回。另请查看此question