我正在尝试从SQL数据库中检索100,000条记录,但在使用ArrayList
时出现内存不足错误。
如何优化我的代码来实现这一目标?如何将flyweight设计模式应用于我的代码?
import java.math.BigDecimal;
import java.util.*;
public class Foo {
public List<Vo> Service(Vo vo) throws Exception {
HashMap<Integer, Object> param = null;
ArrayList<HashMap<String, Object>> getRows = null;
HashMap<String, Object> row = null;
Vo Vo = null;
try {
List<Vo> list = new ArrayList<Vo>();
if (Vo != null) {
param = new HashMap();
if (Vo.getCode() != null) {
param.put(1, Vo.getCode());
param.put(2, Vo.getCode());
}
if (Vo.getCode() != null) {
param.put(3, Vo.getCode());
param.put(4, Vo.getCode());
}
getRows = (ArrayList) ImpDAO.RetrieveQuery(param);
if ((getRows != null) && (getRows.size() > 0)) {
for (Iterator iterator = getRows.iterator(); iterator.hasNext();) {
Vo = new Vo();
row = (HashMap) iterator.next();
if (row.get("CODE") != null)
Vo.setDept((BigDecimal) (row.get("CODE")));
if (row.get("SER") != null)
Vo.setServCode(row.get("SER").toString());
if (row.get("NAME") != null)
list.add(Vo);
}
}
}
} catch (Exception ae) {
throw ae;
}
return list;
}
}
答案 0 :(得分:0)
我看到的最大问题是(ArrayList)ImpDAO.RetrieveQuery(param)
:RetrieveQuery已经返回了一个哈希映射列表。因此,您的数据结构在内存中两次,但它们可能指向相同的对象。
考虑更改RetrieveQuery以返回由底层结果集支持的迭代器(或更好的流)。这将阻止您在内存中保留两个具有相同内容的大型数据结构。
row.get("SER")
的类型是什么?如果答案不是字符串,您可能会为每一行创建一个新字符串。这会大大增加你的内存占用。
row.get(&#34; CODE&#34;)怎么样?这需要是BigDecimal
吗?一个int工作也一样吗?如果是这样,您可以通过切换在每行上保存几个字节。
同时抓住100k行的原因很少。这是显示的ui吗?如果是这样,你真的会一次显示100k行吗?也许你应该看看分页。这是一个处理工作吗?也许我们可以设置限制并以块的形式处理它。
提出这样的问题会让人怀疑underlying problem是什么。
答案 1 :(得分:-1)
您可以尝试修改代码的以下部分,如下所示:
Iterator iterator = getRows.iterator();
while(iterator.hasNext()) {
Vo=new Vo();
row = (HashMap)iterator.next();
if(row.get("CODE") != null )
Vo.setDept((BigDecimal) (row.get("CODE")));
if(row.get("SER") != null )
Vo.setServCode(row.get("SER").toString());
if(row.get("NAME") != null )
list.add(Vo);
}