在大型文件Java中查找重复的行

时间:2014-04-19 20:37:46

标签: java performance duplicates treemap

所以,我有一个包含300万行单词的大文件。我需要看看是否有任何重复。

我将这些行放在TreeMap中,以便对它们进行排序,放置" line"进入关键并给予" 1"他们的价值。当存在重复时,该行的值堆叠起来。然后我将不得不看看是否有任何不是1的值。

这是我的代码:

    BufferedReader list = new BufferedReader( new FileReader( args[0] ) );
    String line;
    TreeMap<String,Integer> map  = new TreeMap<String,Integer>();

    while ( (line = list.readLine()) != null )
    {
        if (!map.containsKey(line)) 
        {
            map.put(line, 0);
        }
        map.put(line, map.get(line) + 1);   
    }

    if ( !map.containsKey(1)  )
    {
        System.out.print("NOT UNIQUE");
    }
    else
    {
        System.out.print("UNIQUE");
    }
    list.close();
}

问题:

  1. 使用TreeMap会加快这个过程吗?或者使用HashMap会有相同/更快的速度吗?

  2. 输出:

    Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at java.lang.Integer.compareTo(Integer.java:52) at java.util.TreeMap.getEntry(TreeMap.java:346) at java.util.TreeMap.containsKey(TreeMap.java:227) at Lab10.main(Lab10.java:22)

  3. if ( !map.containsKey(1) ) ,但我不知道出了什么问题。

6 个答案:

答案 0 :(得分:3)

最有效的实施方式实际上取决于您的要求。

根据你所写的内容:所以,我有一个包含300万行单词的大文件。我需要查看是否有任何重复。,我假设您只是想检查是否有重复的行。

在这种情况下,您不需要计算有多少重复项并使用HashSet,旧的,良好的字符串散列函数可能已经足够好(甚至更好)。

以下是示例:

boolean hasDuplicate = false;
Set<String> lines = new HashSet<String>();
while ( (line = list.readLine()) != null && !hasDuplicate )
    {
        if (lines.contains(line)) {
            hasDuplicate = true;
        }
        lines.add(line);
    }

    if (hasDuplicate){
        System.out.print("NOT UNIQUE");
    } else {
        System.out.print("UNIQUE");
    }
    list.close();
}

答案 1 :(得分:1)

这是一个众所周知的问题Count-Distinct Problem有各种算法:

在Java中,您可以使用BitSet

答案 2 :(得分:0)

地图中的键是String,因此您不能将整数作为键。尝试

if ( !map.containsKey("" + 1)  )

如果您要查找重复内容。也许你可以这样做:

boolean flag = false;
while ( (line = list.readLine()) != null )
    {
        if (!map.containsKey(line)) 
        {
            map.put(line, 0);
        }
        else 
        {
            flag = true;
            break;
        }
    }

    if (flag )
    {
        System.out.print("NOT UNIQUE");
    }
    else
    {
        System.out.print("UNIQUE");
    }
    list.close();
}

此外,由于您不使用该值只是键,因此您可以使用HashSet。

答案 3 :(得分:0)

因为你只是插入行和出现。稍后您将逐个检索,因此不需要排序的地图,您可以使用HashMap。

因为键类型是String所以不能传递整数。

我想你想知道其出现的一行。 所以你可以试试:

如果(map.get(线)!= 1)

{

System.out.print("NOT UNIQUE");

}

否则

{

System.out.print("UNIQUE");

}

答案 4 :(得分:0)

您需要知道的是Set不允许Java中的重复项。这意味着如果您在Set中添加了一个元素并尝试再次插入重复元素,则不允许这样做。在Java中,您可以使用HashSet类来解决此问题。只需遍历数组元素,使用add()方法将它们插入HashSet并检查返回值。如果add()返回false,则表示该集合中不允许该元素,这是您的重复。以下是执行此操作的代码示例:

for (String name : names) {
 if (set.add(name) == false) {
    // your duplicate element
 }}

这个解决方案的复杂性是O(n),因为你只通过数组一次,但由于HashSet数据结构包含你的独特元素,它也具有O(n)的空间复杂度。因此,如果一个数组包含100万个元素,那么在最坏的情况下,您需要一个HashSet来存储这100万个元素。

答案 5 :(得分:0)

Class cast发生异常,因为数据类型不同。如果使用TreeMap,则不支持异构数据类型。