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