你也应该处理你的收藏。
1- 如果您事先知道您的列表会很大,您可以使用ArrayList Capacity。
默认情况下,ArrayList 的初始容量为 10 条记录。当您的列表增长时,java 会不断地(小)重新分配列表,从而浪费大量时间。如果你这样做,例如
List<HashMap<String,String>> userData=new ArrayList<HashMap<String,String>>(500);
你将有一个 500 的 initialCapacity,节省了大量的重新分配,所以时间。
ensureCapacity 方法也很有用,它可以让您的列表增长到用户定义的容量。
因此,如果您事先知道结果的大小,或者至少您有一个想法,您就可以使用它。
否则,如果之后只需要对列表进行迭代,则可以考虑LinkedList,它对于添加操作具有恒定的时间(但对于位置访问没有)。
2- 也考虑一下你的行数据结构,创建一个封装你的结果集列的对象,而不是为每一行创建一个映射(所以很多映射,每个映射都需要一定的内存分配,所以资源和时间),效率会更高。
查看 CollectionFramework 、ArrayList 和 LinkedList 文档
更新
这里有一些“肮脏”的基准
package com.test;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
public class LoopTest {
public static void main(String[] args) {
LoopTest lt=new LoopTest();
int records = 200000;
lt.execute(records, false);
lt.execute(records, true);
lt.executeObj(records, false);
lt.executeObj(records, true);
lt.executeReflect(records, false);
lt.executeReflect(records, true);
}
public void execute(int loops, boolean useCapacity){
Date start=new Date();
System.out.println("EXAMPLE WITH HASHMAP");
System.out.println(start+ " time: "+start.getTime()+" Start for loops="+loops+ " and useCapacity="+useCapacity);
List<HashMap<String,String>> userData=null;
if(useCapacity)
userData=new ArrayList<HashMap<String,String>>(loops);
else
userData=new ArrayList<HashMap<String,String>>();
for(int i=0;i<loops;i++){
HashMap<String,String> recordMap = new HashMap<String,String>();
for (int j = 1; j <= 10; j++) {
String key = j+"";
String value = j+" val";
recordMap.put(key, value);
}
userData.add(recordMap);
}
Date end=new Date();
System.out.println(end+ " time: "+end.getTime()+", elapsed="+(end.getTime()-start.getTime())+" end for loops="+loops+ " and useCapacity="+useCapacity);
System.out.println("-------------------------");
}
public void executeObj(int loops, boolean useCapacity){
System.out.println("EXAMPLE WITH CLASSIC OBJECT");
Date start=new Date();
System.out.println(start+ " time: "+start.getTime()+" Start for loops="+loops+ ", object and useCapacity="+useCapacity);
List<TestObj> userData=null;
if(useCapacity)
userData=new ArrayList<TestObj>(loops);
else
userData=new ArrayList<TestObj>();
for (int i=0;i<loops;i++){
TestObj testObj = new TestObj();
testObj.test1="1";
testObj.test2="1";
testObj.test3="1";
testObj.test4="1";
testObj.test5="1";
testObj.test6="1";
testObj.test7="1";
testObj.test8="1";
testObj.test9="1";
testObj.test10="1";
testObj.test11="1";
testObj.test12="1";
testObj.test13="1";
testObj.test14="1";
testObj.test15="1";
testObj.test16="1";
testObj.test17="1";
testObj.test18="1";
testObj.test19="1";
testObj.test20="1";
userData.add(testObj);
}
Date end=new Date();
System.out.println(end+ " time: "+end.getTime()+", elapsed="+(end.getTime()-start.getTime())+" end for loops="+loops+ ", object and useCapacity="+useCapacity);
System.out.println("-------------------------");
}
public void executeReflect(int loops, boolean useCapacity){
System.out.println("EXAMPLE WITH REFLECTION");
Date start=new Date();
System.out.println(start+ " time: "+start.getTime()+" Start for loops="+loops+ ", object and useCapacity="+useCapacity);
List<TestObj> userData=null;
if(useCapacity)
userData=new ArrayList<TestObj>(loops);
else
userData=new ArrayList<TestObj>();
for (int i=0;i<loops;i++){
try{
Class<?> objClass=Class.forName("com.test.TestObj");
Object myObj=objClass.newInstance();
for(int j=1;j<=20;j++){
Field f=objClass.getDeclaredField("test"+j);
f.set(myObj, "1");
}
userData.add((TestObj)myObj);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Date end=new Date();
System.out.println(end+ " time: "+end.getTime()+", elapsed="+(end.getTime()-start.getTime())+" end for loops="+loops+ ", reflect and useCapacity="+useCapacity);
System.out.println("-------------------------");
}
}
TestObj 是一个仅包含名为 test1...test25 的公共字段的对象。为了简单和快速,我将它们公开,在现实世界中你会将它们设为私有。它可以进行更多设计,但我很快就完成了..
这里是阐述的输出
EXAMPLE WITH HASHMAP, useCapacity=false, loops=200000
Wed Feb 15 06:04:48 CET 2017 time: 1487135088903 Start for loops=200000 and useCapacity=false
Wed Feb 15 06:04:55 CET 2017 time: 1487135095922, elapsed=7019 end for loops=200000 and useCapacity=false
-------------------------
EXAMPLE WITH HASHMAP, useCapacity=true, loops=200000
Wed Feb 15 06:04:55 CET 2017 time: 1487135095922 Start for loops=200000 and useCapacity=true
Wed Feb 15 06:05:01 CET 2017 time: 1487135101073, elapsed=5151 end for loops=200000 and useCapacity=true
-------------------------
EXAMPLE WITH CLASSIC OBJECT, useCapacity=false, loops=200000
Wed Feb 15 06:05:01 CET 2017 time: 1487135101073 Start for loops=200000, object and useCapacity=false
Wed Feb 15 06:05:01 CET 2017 time: 1487135101254, elapsed=181 end for loops=200000, object and useCapacity=false
-------------------------
EXAMPLE WITH CLASSIC OBJECT, useCapacity=true, loops=200000
Wed Feb 15 06:05:01 CET 2017 time: 1487135101254 Start for loops=200000, object and useCapacity=true
Wed Feb 15 06:05:01 CET 2017 time: 1487135101274, elapsed=20 end for loops=200000, object and useCapacity=true
-------------------------
EXAMPLE WITH REFLECTION, useCapacity=false, loops=200000
Wed Feb 15 06:05:01 CET 2017 time: 1487135101274 Start for loops=200000, object and useCapacity=false
Wed Feb 15 06:05:05 CET 2017 time: 1487135105562, elapsed=4288 end for loops=200000, reflect and useCapacity=false
-------------------------
EXAMPLE WITH REFLECTION, useCapacity=true, loops=200000
Wed Feb 15 06:05:05 CET 2017 time: 1487135105562 Start for loops=200000, object and useCapacity=true
Wed Feb 15 06:05:09 CET 2017 time: 1487135109711, elapsed=4149 end for loops=200000, reflect and useCapacity=true
-------------------------
正如您将看到的,使用容量将哈希图示例从大约 7 秒缩短到 5.1 秒。
以经典方式使用对象可以达到 181 毫秒 (!) 甚至 20 毫秒 (!!) 使用数组中的容量。
反射性能与容量的使用无关,大约需要 4 秒(4288 对 4149)。
请注意,基准测试的确切时间可能因执行而异。但总的来说时间顺序总是一样的。
关于以“块”形式获取记录,这是一个很好的内存一致性解决方案,尤其是在您的阐述可能很长的情况下。通常长时间运行的查询可能会出现“快照太旧”错误,这可能会产生问题。而且也不确定性能会因此而下降很多。
在过去,我必须处理类似的事情,一个非常好的解决方案是在源表中放置一个带有索引的字段“chunk_id”,这样可以轻松地重复我对“下一个”行的查询,并给了我更多效率高于检索表的所有内容。一般来说,您只需要一种方法来识别您的记录组,例如第 1 组、第 2 组、.. 第 n 组(当然,还要在其中放置索引。
PS反射的例子很简单,但这只是为了展示如何做,你可以使用很多特性,包括方法等