Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.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 HashMap速度变慢了?_Java_Hashmap_Bufferedreader - Fatal编程技术网

为什么Java HashMap速度变慢了?

为什么Java HashMap速度变慢了?,java,hashmap,bufferedreader,Java,Hashmap,Bufferedreader,我尝试用一个文件的内容构建一个地图,我的代码如下: System.out.println("begin to build the sns map...."); String basePath = PropertyReader.getProp("oldbasepath"); String pathname = basePath + "\\user_sns.txt"; FileReader fr; Map<Integer, List<Integer

我尝试用一个文件的内容构建一个地图,我的代码如下:

    System.out.println("begin to build the sns map....");
    String basePath = PropertyReader.getProp("oldbasepath");
    String pathname = basePath + "\\user_sns.txt";
    FileReader fr;
    Map<Integer, List<Integer>> snsMap = 
            new HashMap<Integer, List<Integer>>(2000000);
    try {
        fr = new FileReader(pathname);
        BufferedReader br = new BufferedReader(fr);
        String line; 
        int i = 1;
        while ((line = br.readLine()) != null) {
            System.out.println("line number: " + i);
            i++;

            String[] strs = line.split("\t");
            int key = Integer.parseInt(strs[0]);
            int value = Integer.parseInt(strs[1]);
            List<Integer> list = snsMap.get(key);
            //if the follower is not in the map
            if(snsMap.get(key) == null) 
                list = new LinkedList<Integer>();
            list.add(value);
            snsMap.put(key, list);
            System.out.println("map size: " + snsMap.size());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.out.println("finish building the sns map....");
    return snsMap;
我尝试使用两个System.out.println()子句来判断BufferedReader和HashMap的性能,而不是Java探查器。
有时在获取线号信息后需要一段时间才能获取地图大小信息,有时在获取地图大小后需要一段时间才能获取线号信息。我的问题是:是什么让我的程序变慢了?大文件的BufferedReader还是大映射的HashMap

您必须使用一些分析工具检查您的程序,以了解其速度慢的原因。
一般来说,文件访问比内存中的操作慢得多(除非您在内存中受到限制,并且执行过多的GC),所以这里的猜测是读取文件可能会更慢。

最好的方法是使用探查器(例如,JProfile)运行您的程序,并查看哪些部分比较慢。例如,调试输出也会减慢程序的速度。

如果您是从Eclipse内部进行测试的,您应该知道写入stdout/stderr会造成巨大的性能损失,因为Eclipse会在控制台视图中捕获该输出。即使在Eclipse之外,在紧密循环中打印也是一个性能问题


但是,如果你抱怨的是在处理了3000万行之后速度变慢,那么我打赌这是内存问题。首先,由于频繁的GC'ing,它会减慢速度,然后会因
OutOfMemoryError
而中断。哈希映射并不慢,但实际上它是所有映射中速度最快的。HashTable是映射中唯一的线程安全的,有时速度会很慢

重要提示:读取数据后关闭BufferedReader和文件。。。这可能会有帮助

例如:br.close() file.close()文件

请从任务管理器检查您的系统进程,可能有太多进程在后台运行


有时候,eclipse是真正的资源密集型,所以试着从控制台运行它来检查它。

在您分析之前,您将不知道什么慢,什么不慢。

最有可能的是,
System.out
将显示为瓶颈,然后您将不得不再次在没有它们的情况下进行评测
System.out
是查找性能瓶颈最糟糕的方法,因为这样做通常会增加更糟糕的瓶颈

对代码的一个明显优化就是移动代码行

snsMap.put(key, list);
输入
if
语句。您只需要在创建新列表时放置此项。否则,put将仅用自身替换当前值

Integer
对象相关的Java成本(尤其是在Java Collections API中使用整数)在很大程度上是一个内存问题(因此垃圾收集!)。有时,通过使用诸如之类的基本集合,您可以获得显著的收益,这取决于您如何调整代码以有效地使用它们。Trove的大部分收益来自内存使用。一定要尝试重写代码以使用GNU-trove中的
TIntArrayList
TIntObjectMap
。我也会避免使用链表,特别是对于基本类型

粗略估计,
HashMap
每个条目至少需要3*16字节。双链接列表同样需要每个存储的条目至少2*16字节。1m键+30m值~1GB。还不包括间接费用。使用GNU-trove
TIntObjectHash
时,每个键应为4+4+16字节,每个值应为4字节,因此为144 MB。两者的开销可能相似

Trove使用更少内存的原因是,这些类型专门用于基本值,如
int
。它们将直接存储
int
值,因此使用4个字节来存储每个值

Java集合
HashMap
由许多对象组成。大致如下:有
Entry
对象分别指向一个键和一个值对象。由于Java中处理泛型的方式,这些对象必须是对象。在您的情况下,键将是一个
整数
对象,它使用16个字节(4个字节标记,4个字节类型,4个字节实际
int
值,4个字节填充)AFAIK。这些都是32位系统估计值。因此,
HashMap
中的单个条目可能需要16(条目)+16(整数键)+32(但LinkedList为空)字节的内存,这些都需要考虑垃圾收集


如果您有大量的
Integer
对象,那么所需的内存将是使用
int
原语存储所有对象所需内存的4倍。这是在Java中实现的干净OOP原则的成本。

为什么要调用两次
get
?不要将现有列表放到映射中。使用探查器,您将不必猜测什么是慢的,什么是快的…从while循环中删除System.out.println,然后重试。映射中有超过110万个LinkedList。你的记忆力是否已经耗尽?我对这个问题投了否决票,因为它不能用所提供的信息客观地回答,所有答案中的猜测都证明了这一点。为了有效地查明Java性能问题,使用探查器(或类似于线程转储之类的评测)是目前为止最好的方法。但是程序一开始非常快,过一段时间就会慢下来。我试图找出System.out.println()的问题@AKJ有时测量程序的行为会改变程序的特性。通过测量,我指的是System.out.println()。使用剖析器;就是为了这个。众所周知,大量使用
System.out.println
会对性能产生重大影响。标准输出不利于调试性能问题。请参阅我关于如何使用GNU Trove原语集合将内存使用量减少5-10倍的回复。粗略估计,
HashMap
至少需要3*16字节pe
snsMap.put(key, list);