Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.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_Memory Leaks_Hashtable - Fatal编程技术网

Java中的哈希表内存使用

Java中的哈希表内存使用,java,memory-leaks,hashtable,Java,Memory Leaks,Hashtable,我使用java从文件中读取数据,将数据复制到较小的数组中,并将这些数组放入哈希表中。我注意到Hashmap比原始文件消耗更多的内存(大约两倍)!知道为什么吗 这是我的密码: public static void main(final String[] args) throws IOException { final PrintWriter writer = new PrintWriter(new FileWriter("test.txt", true));

我使用java从文件中读取数据,将数据复制到较小的数组中,并将这些数组放入哈希表中。我注意到Hashmap比原始文件消耗更多的内存(大约两倍)!知道为什么吗

这是我的密码:

public static void main(final String[] args) throws IOException {
    final PrintWriter writer = new PrintWriter(new FileWriter("test.txt",
            true));
    for(int i = 0; i < 1000000; i++)
        writer.println("This is just a dummy text!");
    writer.close();

    final BufferedReader reader = new BufferedReader(new FileReader(
            "test.txt"));
    final HashMap<Integer, String> testMap = new HashMap<Integer, String>();
    String line = reader.readLine();
    int k = 0;
    while(line != null) {
        testMap.put(k, line);
        k++;
        line = reader.readLine();
    }
}
publicstaticvoidmain(最终字符串[]args)引发IOException{
final PrintWriter=新的PrintWriter(新文件编写器(“test.txt”),
是的);
对于(int i=0;i<1000000;i++)
println(“这只是一个伪文本!”);
writer.close();
final BufferedReader reader=新BufferedReader(新文件读取器(
"test.txt),;
final HashMap testMap=新HashMap();
字符串行=reader.readLine();
int k=0;
while(行!=null){
testMap.put(k,line);
k++;
line=reader.readLine();
}
}

HashMap(和数组)的实现中有许多内部内容需要存储。数组长度就是这样一个例子。不确定这是否会造成双重损失,但肯定会造成一些损失。

这不是HashMap的问题,而是Java对象的问题。每个对象都有一定的内存开销,包括
HashMap
中的数组和条目

但更重要的是:字符数据占用内存空间的两倍。原因是,尽管文件可能是用ASCII或UTF-8编码的,但每个字符只使用7或8位

更新:对此您无能为力。你发布的代码原则上是好的。它不能处理大文件。如果仔细调整
HashMap
,或者使用字节数组而不是字符串来存储字符(假设所有内容都是ASCII或单字节UTF-8),您可能会做得更好一些

但最终,要解决内存不足的问题,正确的方法是重新思考程序,这样就不必一次将整个文件读入内存

无论您如何处理该文件的内容,请考虑是否可以在从磁盘读取该文件时执行此操作(这称为流式处理),或者提取相关部分并仅存储这些部分。您也可以尝试随机访问文件

我建议你读一读这些东西,尝试一些东西,然后回来问一个新问题,具体到你的应用程序。因为这个线程太长了。

映射是一个“可扩展”的结构-当它达到其容量时,它会被调整大小。因此,有可能说地图使用的40%的空间实际上是空的。如果您知道地图中将有多少个条目,则可以使用特殊构造函数以最佳方式调整地图的大小:

Map<xx,yy> map = new HashMap<> (length, 1);
这表明,如果您添加的最后一个项目碰巧强制地图调整大小,它可能会人为地增加地图的大小。诚然,这并不能解释你所观察到的全部效果

public static void main(String[] args) throws java.lang.Exception {
    Field f = HashMap.class.getDeclaredField("threshold");
    f.setAccessible(true);

    long mem = Runtime.getRuntime().freeMemory();
    Map<String, String> map = new HashMap<>(2 << 12, 1); // 8,192
    System.out.println("threshold of empty map = " + f.get(map));
    System.out.println("size of empty map = " + (mem - Runtime.getRuntime().freeMemory()));

    mem = Runtime.getRuntime().freeMemory();
    for (int i = 0; i < 8192; i++) {
        map.put(String.valueOf(i), String.valueOf(i));
    }
    System.out.println("threshold of filled map = " + f.get(map));
    System.out.println("size of filled map = " + (mem - Runtime.getRuntime().freeMemory()));

    mem = Runtime.getRuntime().freeMemory();
    map.put("a", "a");
    System.out.println("threshold with one more entry = " + f.get(map));
    System.out.println("size with one more entry = " + (mem - Runtime.getRuntime().freeMemory()));
}
publicstaticvoidmain(字符串[]args)抛出java.lang.Exception{
字段f=HashMap.class.getDeclaredField(“阈值”);
f、 setAccessible(true);
long mem=Runtime.getRuntime().freemory();

Map Map=新的HashMap(2)一些代码是值得赞赏的。哈希表有相当大的开销——作为交换,它支持固定时间查找。@LouisWasserman我不认为开销会造成这样的差异。是的,我读到过@assylias,但当它的容量翻倍时,不是它的实际大小。比如,如果值是对象引用,那么它知道需要多少内存吗?我不认为HashMap的开销是问题所在。毕竟,未使用的条目只消耗一个指针大小的内存块,即8或16字节。包含数据的数组可能要大得多。@user1785771发布代码的相关部分,那么我们可能可以帮助您。+1表示f下面;-)事实上,如果这段代码的内存不足,除了不将整个文件存储在内存中之外,没有什么可做的。
public static void main(String[] args) throws java.lang.Exception {
    Field f = HashMap.class.getDeclaredField("threshold");
    f.setAccessible(true);

    long mem = Runtime.getRuntime().freeMemory();
    Map<String, String> map = new HashMap<>(2 << 12, 1); // 8,192
    System.out.println("threshold of empty map = " + f.get(map));
    System.out.println("size of empty map = " + (mem - Runtime.getRuntime().freeMemory()));

    mem = Runtime.getRuntime().freeMemory();
    for (int i = 0; i < 8192; i++) {
        map.put(String.valueOf(i), String.valueOf(i));
    }
    System.out.println("threshold of filled map = " + f.get(map));
    System.out.println("size of filled map = " + (mem - Runtime.getRuntime().freeMemory()));

    mem = Runtime.getRuntime().freeMemory();
    map.put("a", "a");
    System.out.println("threshold with one more entry = " + f.get(map));
    System.out.println("size with one more entry = " + (mem - Runtime.getRuntime().freeMemory()));
}