使用Hashmap保存大值时发生的outofmemory错误

时间:2012-03-12 15:40:26

标签: java oracle collections map

我有一个简单的对象:

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或其他方式可以避免这个问题?

2 个答案:

答案 0 :(得分:2)

保存这么多不能适合可用内存的对象是不可能的。有两种解决方案。首先是使用缓存,该缓存将持久存储到无法放入内存的本地文件对象中。像ehcache这样的东西。第二种解决方案是使用对象切换到二维数组

long[][] cache = new long[1000*1000][];
long[] row = new long[2];

row会保留mToIdmType。使用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倍。
  • 我建议您使用TLongObjectHashMap,这样可以更有效地存储密钥。

每个条目大约使用64个字节。如果你需要一个更紧凑的形式,你可以做到这一点,但复杂性越来越高。每个条目不会超过20个字节。