Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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 ArrayList排序,应用程序卡住_Java_Sorting_Arraylist - Fatal编程技术网

Java ArrayList排序,应用程序卡住

Java ArrayList排序,应用程序卡住,java,sorting,arraylist,Java,Sorting,Arraylist,我有一个ArrayList,里面填充了文本文件中的单词,我需要根据单词的出现情况进行排序,从出现次数最多到出现次数较少。我将带有单词的原始ArrayList复制到另一个ArrayList,并在顶部添加出现的次数。因此,新ArrayList中的单词将看起来,例如: password:125,其中password是单词,125是ArrayList中出现的次数 for (int i=0;i<sorter.size();i++) { sorter2.add(

我有一个ArrayList,里面填充了文本文件中的单词,我需要根据单词的出现情况进行排序,从出现次数最多到出现次数较少。我将带有单词的原始ArrayList复制到另一个ArrayList,并在顶部添加出现的次数。因此,新ArrayList中的单词将看起来,例如: password:125,其中password是单词,125是ArrayList中出现的次数

for (int i=0;i<sorter.size();i++) {
                    sorter2.add(sorter.get(i)+":"+Collections.frequency(sorter, sorter.get(i)));
                }
之后,我使用以下类对ArrayList进行排序:

public class RepeatFormulaCounter implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        if (findValue(o2) != findValue(o1)) {
            return findValue(o2) - findValue(o1); 
        }
        return o2.compareTo(o1);
    }
    public int findValue(String find){
        int result=0;
        String spliter[]=find.split(":");        
        result=Integer.parseInt(spliter[1]);
        return result;
    }


}
但是,由于我有5个文本文件,其中3个文件大约有45000个单词,2个文件超过1000000个单词,因此45000个单词左右的文件在排序和显示时没有任何问题,但是当我开始对超过1000000个单词的文件进行排序时,应用程序被卡住了。为什么会这样?我怎样才能修好它


请注意,我正在使用GUI应用程序来显示它。我使用了两个类似的排序类,用于按不同标准进行排序的其他方法,这些方法的显示和执行没有任何问题。

我认为问题可能超出了所示代码的范围,但您可以尝试通过减少查找调用的数量以及当前创建的对象的数量来减少对象垃圾,每次查找调用都会创建3个新对象,并在比较中调用查找4次:

@Override
public int compare(String o1, String o2) {
    int f2 = findValue(o2);
    int f1 = findValue(o1);
    if (f2 != f1) {
        return f2 - f1; 
    }
    return o2.compareTo(o1);
}

public int findValue(String find){
    int result = 0;
    int cut = find.lastIndexOf(':');
    result = Integer.parseInt(find.substring(cut + 1));
    return result;
}
通过去掉子字符串,这可能会得到更多的改进

可能更好的选择是将用于计数的映射交给比较器构造函数,然后在比较器中使用它:

public class CountComparator implements Comparator<String> {
  Map<String, Integer> counts;
  public CountComparator(Map<String, Integer> counts) {
    this.counts = counts;
  }

  public int compare(String o1, String o2) {
    int f2 = counts.get(o2);
    int f1 = counts.get(o1);
    if (f1 != f2) {
      return f2 - f1;
    } 
    return o2.compareTo(o1);
  }
}
为什么要将单词存储为密码:125?你的工作效率很低。您必须使用有效的数据结构来存储单词的统计信息。使用Map接口并选择正确的实现来存储单词及其引用

Map<String, Integer> wordsMap = new HashMap<String,Double>();

/* Fill the wordsMap with data, then use this function to sort.
  Fill and update value by key is simple:

  wordsMap .put(key, 50); <-- put value
  wordsMap .put(key, map.get(key) + 1); <--- update value

  For example:

  wordsMap .put("google", 0); <-- put value
  wordsMap .put("google", map.get("google") + 1); <--- increment value by 1

*/

public static <K, V extends Comparable<? super V>> Map<K, V> 
    sortByValue( Map<K, V> map )
{
    List<Map.Entry<K, V>> list =
        new LinkedList<>( map.entrySet() );
    Collections.sort( list, new Comparator<Map.Entry<K, V>>()
    {
        @Override
        public int compare( Map.Entry<K, V> o1, Map.Entry<K, V> o2 )
        {
            return (o1.getValue()).compareTo( o2.getValue() );
        }
    } );

    Map<K, V> result = new LinkedHashMap<>();
    for (Map.Entry<K, V> entry : list)
    {
        result.put( entry.getKey(), entry.getValue() );
    }
    return result;
}

// sortByValue(wordsMap);
此外,您还可以阅读Hashtable、LinkedHashMap、TreeMap等类,然后选择性能更好的类。它们实现相同的映射接口,但对于put、get和其他方法的内部实现具有不同的渐近性

Sun针对每个集合类的Javadocs通常会准确地告诉您想要什么

HashMap,例如:

此实现为基本的 操作get和put,假设散列函数将 在桶之间正确地放置元素。集合视图上的迭代 需要与HashMap实例的容量成比例的时间 存储桶的数量加上其大小即为键值的数量 映射

树形图:

此实现为服务器提供了有保证的logn时间成本 containsKey、get、put和remove操作

树集:

此实现为基本的服务提供了有保证的logn时间成本 操作添加、删除和包含


如果仍然比预期的慢,那么可以使用多线程。如果您的处理器有8个核,您可以将文件拆分为8个和平,在8个线程中计算字数,合并结果,然后运行排序。

很可能是内存问题。尝试增加jvm堆大小。您创建了大量的临时字符串,并且您的垃圾收集器在大数据量时会变得疯狂。

利用Java 8中引入的流。它们非常适合处理数据

HashMap<String, Integer> occurences = new HashMap<>();
...
Stream<String> stream = occurences.entrySet().stream()
    .sorted((a, b) -> b.getValue() - a.getValue())
    .map(kv -> kv.getKey());
String[] sortedWords = stream.toArray(size -> new String[size]);

在GUI中显示什么?您正在使用什么GUI组件?更可能的问题是GUI组件无法处理太多的数据点。因为排序不是一项简单的任务。您使用什么算法进行排序?无论如何,您都应该加快比较函数的速度,不要对两个对象调用findValue两次。如果你做整数解析的次数超过1000万次,那么它的代价是相当高的。我在JTextArea上通过添加这10个单词来显示出现频率最高的前10个单词。Ok。程序可能会被卡住,因为它正在生成大量垃圾并有许多GC循环。您可以使用jconsole或jvisualvm检查这一点。至少你们可以确定程序是否因为cpu负载或内存问题而被卡住。谢谢你们的回答,伙计们,我需要一段时间来理解并尝试一切那么排序部分呢?谢谢你的回答,它让我走上了正确的道路。我刚刚测试了代码的性能。即使HashMap包含100万个不同的字符串,也只需不到1秒的时间,占用的内存也不到200 MB。感谢您的回答,它也以不同的方式帮助了我。您可能希望对所有有用的答案进行投票,并接受解决问题的答案…O: