我有一个简单的对象:
public class ActVO
{
private Long mFromId;
private Long mToId;
private int mType;
}
它也一直存在于Oracle DB中。目前,存储的行在DB中大约有100万。我想通过使用mFromId作为键将这些行读取到内存并缓存到HashMap。
我的问题是,当读取到400,000行时,它发生了内存错误(启动内存已准备好分配给1G)。我使用了cern.colt.map.OpenLongObjectHashMap和sun HasHmap它们都遇到了同样的问题。
每个人都可以告诉哪个第3张地图api或其他方式可以避免这个问题?
答案 0 :(得分:2)
保存这么多不能适合可用内存的对象是不可能的。有两种解决方案。首先是使用缓存,该缓存将持久存储到无法放入内存的本地文件对象中。像ehcache这样的东西。第二种解决方案是使用对象切换到二维数组
long[][] cache = new long[1000*1000][];
long[] row = new long[2];
row
会保留mToId
和mType
。使用cache
作为索引将行插入mFromId
。
以下是一个例子:
Random r = new Random();
class ActVO {
private long mFromId;
private long mToId;
private int mType;
}
int capacity = 1000*1000;
List<ActVO> resultSet = new ArrayList<ActVO>();
for (int i = 0; i < capacity; i++) {
ActVO element = new ActVO();
element.mFromId = i;
element.mToId = r.nextLong();
// let's say there are not more than 10 types
element.mType = r.nextInt(10);
resultSet.add(element);
if (i == 57) {
System.out.printf(" db result 57: mToId=%d, mType=%d\n", element.mToId, element.mType);
}
}
long[][] cache = new long[capacity][];
// iterating trough a database set
for (ActVO element : resultSet) {
long[] row = new long[2];
row[0] = element.mToId;
row[1] = element.mType;
cache[(int) element.mFromId] = row;
}
System.out.printf("57th row from cache: mToId=%d, mType=%d\n", cache[57][0], cache[57][1]);
答案 1 :(得分:0)
我的建议是;
Long
时,请勿使用long
。它的内存可以大5倍。每个条目大约使用64个字节。如果你需要一个更紧凑的形式,你可以做到这一点,但复杂性越来越高。每个条目不会超过20个字节。