一个简单的笨重Map,内存中保存一些对象,其他的保存到硬盘。
2014-06-26 16:01
309 查看
今天观看论坛,发现有些初学者,总是将大量的数据存入HashMap中,造成内存溢出。
问题的关键是,造成溢出以后,不去改进算法,而是机械的调节JVM的最大内存容量,这并不能从根本上解决问题。
除了B+Tree等较好的算法以外,我想来想去,还有一个相对简单点的实现方案,就是效率硬盘没有索引,效率相对较低。
代码如下:
问题的关键是,造成溢出以后,不去改进算法,而是机械的调节JVM的最大内存容量,这并不能从根本上解决问题。
除了B+Tree等较好的算法以外,我想来想去,还有一个相对简单点的实现方案,就是效率硬盘没有索引,效率相对较低。
代码如下:
import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.util.HashSet; import java.util.LinkedHashMap; public class HeavyMap extends LinkedHashMap<String, Integer> { private static final long serialVersionUID = -858815745597381386L; public static final int DEFAULT_CAPACITY = 2000; public static final String File_Prefix = "heavy_map"; public static final String File_Suffix = "bin"; private int capacity;// 内存对象容量 private RandomAccessFile switchFile;// 数据交换文件 private HashSet<Integer> virtualCache = new HashSet<Integer>(); public HeavyMap() throws IOException { this(DEFAULT_CAPACITY); } public HeavyMap(int capacity) throws IOException { this(capacity, File.createTempFile(File_Prefix, File_Suffix)); } public HeavyMap(int capacity, File switchFile) throws IOException { super(16, 0.75f, true); this.capacity = capacity; if (switchFile.isDirectory()) { switchFile = File.createTempFile(File_Prefix, File_Suffix, switchFile); } this.switchFile = new RandomAccessFile(switchFile, "rw"); } @Override public Integer put(String key, Integer value) { virtualCache.add(key.hashCode()); return super.put(key, value); } @Override protected boolean removeEldestEntry( java.util.Map.Entry<String, Integer> eldest) { if (size() >= capacity) { updateEntry(eldest); return true; } return false; } @Override public Integer get(Object key) { Integer value = super.get(key); if (value == null && virtualCache.contains(key.hashCode())) { Integer v = findValue((String) key); if (v != null) { put((String) key, v); } } return value; } private Integer findValue(Object key) { synchronized (switchFile) { try { switchFile.seek(0L); long length = switchFile.length(); while (switchFile.getFilePointer() < length) { int hash = switchFile.readInt(); int len = switchFile.readInt(); if (hash == key.hashCode()) { byte[] data = new byte[len - 4]; if (switchFile.read(data) < 0) { throw new EOFException(); } int valueNumber = switchFile.readInt(); String keyString = new String(data, "UTF-8"); if (keyString.equals(key)) { return valueNumber; } } else { switchFile.skipBytes(len); } } } catch (EOFException e) { return null; } catch (IOException e) { throw new IllegalStateException("读取交换区数据时产生异常", e); } } return null; } private void updateEntry(java.util.Map.Entry<String, Integer> e) { synchronized (switchFile) { try { switchFile.seek(0L); long length = switchFile.length(); while (switchFile.getFilePointer() < length) { int hash = switchFile.readInt(); int len = switchFile.readInt(); if (hash == e.getKey().hashCode()) { byte[] data = new byte[len - 4]; if (switchFile.read(data) < 0) { throw new EOFException(); } int valueNumber = switchFile.readInt(); String keyString = new String(data, "UTF-8"); if (keyString.equals(e.getKey()) && valueNumber != e.getValue()) { switchFile.seek(switchFile.getFilePointer() - 4); switchFile.writeInt(e.getValue()); } } else { switchFile.skipBytes(len); } } } catch (IOException ex) { throw new IllegalStateException("读取交换区数据时产生异常", ex); } } } @Override public void clear() { super.clear(); virtualCache.clear(); } @Override protected void finalize() throws Throwable { super.finalize(); switchFile.close(); } }
相关文章推荐
- 如何简单的下载一些小文件并保存在一个路径中(有些方法进行了封装)
- for环中创建map,创建的是一个map对象还是多,map和内存的问题
- 一个简单的Delphi框架-xDom-1 内存对象
- 一个简单的内存同步到数据库的方法
- 自已创建一个含一些记录的DataTable – 就这样简单
- 一个简单的把对象序列化/反序列化为json格式的程序
- 保存数据库中其他对象不变,删除数据库中所有数据的实现方法
- 为什么一个对象调用的类方法可以访问该类其他对象的私有成员
- [C#]租约的Renew和“在主机应用程序域运行时始终”将对象保存在内存中
- 一个简单的能处理MIP-MAP的类
- 计算机科学与技术学习心得之计算机理论的一个核心问题--续谈其他的一些计算数学(转载)
- 共享内存对象方法(MapViewOfFile)
- AJAX实现一个简单的相册和里头包含一些DOM基础应用
- 一个比较容易调用 功能比较完善的 cookie 操作类 附带一些简单的应用示例
- [C#]租约的Renew和“在主机应用程序域运行时始终”将对象保存在内存中
- PHP在后台启动Microsoft Word、打开一个新文件、键入一些文本、保存该文件然后关闭应用程序
- 遇到一个很难说话的人,要求在网页上点一下文字,变成另外一些文字,下面是简单的实现
- 一个简单的动态编译器,支持C#和VB.NET。当你想测试一些简单的代码的时候可以使用。
- symbian中活动对象的一些简单的使用
- 简单的问题,用类创建一个对象error C2380: type(s) preceding 'Complex' (constructor with return type, or illegal redefinition of current class-n