Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在大型数据集中查找唯一项的最有效方法_Java_Arrays_Sorting_Search_Arraylist - Fatal编程技术网

Java 在大型数据集中查找唯一项的最有效方法

Java 在大型数据集中查找唯一项的最有效方法,java,arrays,sorting,search,arraylist,Java,Arrays,Sorting,Search,Arraylist,在此之前,我要明确这是一项作业,我不希望得到完整的编码答案。我所寻求的只是建议,也许还有一些能帮助我的代码片段 所以,我读了大约900000个单词,全部存储在arrayList中。我需要在java中使用排序数组或arraylist来计算唯一的单词 到目前为止,我只是在给定的arrayList和use上循环 Collections.sort(words); 和Collections.binarySearchwords,wordToLook;要实现此目标,请执行以下操作: OrderedSet

在此之前,我要明确这是一项作业,我不希望得到完整的编码答案。我所寻求的只是建议,也许还有一些能帮助我的代码片段

所以,我读了大约900000个单词,全部存储在arrayList中。我需要在java中使用排序数组或arraylist来计算唯一的单词

到目前为止,我只是在给定的arrayList和use上循环

Collections.sort(words); 
和Collections.binarySearchwords,wordToLook;要实现此目标,请执行以下操作:

OrderedSet set = new OrderedSet();
    for(String a : words){
        if(!set.contains(a)){
            set.add(a);
        }
    }

这段代码的运行时间约为60秒,但我想知道是否有更好的方法来实现这一点,因为每次添加元素时运行排序似乎效率很低,但如果我要使用二进制搜索,这是必要的


任何形式的反馈都将不胜感激。谢谢。

我不会使用排序数组。我会创建一个地图,其中关键字是单词,值是单词出现次数的计数。阅读每个单词时,请执行以下操作:

Integer count = map.get(word);
if (count == null) {
    count = 0;
}
map.put(word, count + 1);
然后只需迭代映射的条目集,并对计数执行任何需要执行的操作

如果您知道或可以估计唯一单词的数量,那么您应该在HashMap构造函数中使用这个数字,这样就不会使映射增长很多次

如果使用排序数组,则运行时间与NlogN成正比,其中N是列表中的字数。如果您使用HashMap,您可以实现一个随N线性增长的运行时,您可以保存logN的因子

使用映射的另一个优点是,使用的内存与唯一单词的数量成正比,而不是假设您在读取单词时构建映射,而不是将所有单词读入集合然后添加到映射中,则与单词的总数成正比。

因此,您需要使用排序数组。这没关系,因为您还没有在现实世界中编程

我将提出两个备选方案:

第一种方法使用二进制搜索,您在当前代码中使用的是二进制搜索

我将创建一个包含两个字段的类:单词字符串和该单词的计数int。您将构建这些类的排序数组

从一个空数组开始,在阅读每个单词时添加到该数组中。对于每个单词,对正在构建的数组中的单词进行二进制搜索。搜索将找到包含该单词的条目并增加计数,或者确定该单词尚未在数组中

当您的二进制搜索结束时没有找到单词,您将创建一个新对象来保存单词+计数,并将其添加到搜索结束位置的数组中。小心确保您的逻辑确实将其放置在正确的位置,以保持列表排序。当然,新单词的计数设置为1

另一种选择:

把你所有的单词都读成一个列表,并进行排序。排序后,所有重复项将在列表中彼此相邻

您将在这个排序列表中遍历一次,并创建一个word+count列表。如果看到的下一个单词与上一个单词+计数相同,则增加计数。如果是一个新词,请在结果列表中添加一个新词+计数,计数=1

public static int countUnique(array) {
    if(array.length == 0) return 0;
    int count = 1;
    for i from 1 to array.length - 1 {
        if(!array[i].equals(array[i - 1])) count++;
    }
    return count;
}
这是一个伪代码中的ON算法,用于计算排序数组中唯一项的数量。其背后的思想是,我们计算相等元素组之间的转换次数。然后,唯一条目的数量是转换的数量加上第一个条目的数量


希望您能看到如何在元素排序后将此算法应用于数组。

您始终可以使用comparator获得唯一值

  List newList = new ArrayList(new Comparator() {
        @Override
        public int compare(words o1, words o2) {
            if(o1.equalsIgnoreCase(o2)){
                return 0;
            }
            return 1;
        }
    });
现在计算:

words-newList=重复值的数量


希望这有帮助

你永远不应该每次添加元素时都运行排序。是的,但是还有什么替代方法呢?如果你有一个排序数组,你可以通过在数组上循环一次来计算线性时间内的唯一单词。你知道这是怎么可能的吗?您不必使用二进制搜索。正如@IRelephant所说,无需在每次添加元素时对数组进行排序。您可以在适当的位置添加元素,避免排序。请看一个名为InsertionSort的算法。我非常喜欢使用映射,我被迫使用排序数组,因为这是一个要求。。
  List newList = new ArrayList(new Comparator() {
        @Override
        public int compare(words o1, words o2) {
            if(o1.equalsIgnoreCase(o2)){
                return 0;
            }
            return 1;
        }
    });