java 较大数据量取差集,list.removeAll性能优化详解
今天在优化项目中的考勤同步功能时遇到将考勤机中的数据同步到数据库,
两边都是几万条数据的样子,老代码的做法差不多半个小时,优化后我本机差不多40秒,服务器速度会更加理想。
两个数据集取差集首先想到的方法便是List.removeAll方法,但是实验发现jdk自带的List.removeAll效率很低
List.removeAll效率低原因:
List.removeAll效率低和list集合本身的特点有关:
List底层数据结构是数组,查询快,增删慢
1.List.contains()效率没有hashset高
arrayList.removeAll底层是for循化调用contains方法。arrayList虽然用get(index)方法查询效率高,但是若用contains方法查询对象元素,Set集合应该比List效率要高。
因为hashset的contains方法其实是先调用每个元素的hashCode()方法来返回哈希码,如果哈希码的值相等的情况下再调用equals(obj)方法去判断是否相等,只有在这两个方法所返回的值都相等的情况下,才判定这个HashSet包含某个元素,而list直接调用equals(obj)方法.所以hashset效率更高。
2.arrayList.remove()效率没有linkedList删除效率高
arrayList底层采用数组每删除一下元素数据后面的元素都要往前移动效率低消耗的资源也大,linkedList链表删除元素只要改变前后节点的位置信息
3.采用Iterator迭代器,这种方式我们仅需要对iterator进行循环,然后对需要删除的元素执行iterator.remove(iterator.next()),而无需关注下标的问题
改进代码
LinkedListlinkedList=newLinkedList(src);//大集合用linkedlist
HashSethashSet=newHashSet(oth);//小集合用hashset
Iteratoriter=linkedList.iterator();//采用Iterator迭代器进行数据的操作
while(iter.hasNext()){
if(hashSet.contains(iter.next())){
iter.remove();
}
}
补充知识:JAVA获取两个数据量较大的ArrayList的交集、差集以及并集
测试说明:获取firstArrayList和secondArrayList的交集、差集以及并集。实际测试中firstArrayList数据量190000,secondArrayList数据量170000.效率比较高。此处只列出少量数据。测试代码如下:
importjava.util.Set;
importjava.util.List;
importjava.util.HashSet;
importjava.util.TreeSet;
importjava.util.Iterator;
importjava.util.ArrayList;
importjava.util.LinkedList;
publicclassgetSet{
publicstaticvoidmain(Stringargs[]){
getList();
}
//获取两个ArrayList的差集、交集、去重并集(数据量大小不限制)
privatestaticvoidgetList(){
ListfirstArrayList=newArrayList();
ListsecondArrayList=newArrayList();
ListdefectList=newArrayList();//差集List
ListcollectionList=newArrayList();//交集List
ListunionList=newArrayList();//去重并集List
try{
firstArrayList.add("aaa");
firstArrayList.add("bbb");
firstArrayList.add("ccc");
firstArrayList.add("ddd");
secondArrayList.add("bbb");
secondArrayList.add("ccc");
secondArrayList.add("eee");
//获取差集
defectList=receiveDefectList(firstArrayList,secondArrayList);
IteratordefectIterator=defectList.iterator();
System.out.println("===================差集===================");
while(defectIterator.hasNext()){
System.out.println(defectIterator.next());
}
//获取交集
collectionList=receiveCollectionList(firstArrayList,secondArrayList);
IteratorcollectionIterator=collectionList.iterator();
System.out.println("===================交集===================");
while(collectionIterator.hasNext()){
System.out.println(collectionIterator.next());
}
//获取去重并集
unionList=receiveUnionList(firstArrayList,secondArrayList);
IteratorunionIterator=unionList.iterator();
System.out.println("===================去重并集===================");
while(unionIterator.hasNext()){
System.out.println(unionIterator.next());
}
}catch(Exceptione){
e.printStackTrace();
}
}
/**
*@方法描述:获取两个ArrayList的差集
*@paramfirstArrayList第一个ArrayList
*@paramsecondArrayList第二个ArrayList
*@returnresultList差集ArrayList
*/
publicstaticListreceiveDefectList(ListfirstArrayList,ListsecondArrayList){
ListresultList=newArrayList();
LinkedListresult=newLinkedList(firstArrayList);//大集合用linkedlist
HashSetothHash=newHashSet(secondArrayList);//小集合用hashset
Iteratoriter=result.iterator();//采用Iterator迭代器进行数据的操作
while(iter.hasNext()){
if(othHash.contains(iter.next())){
iter.remove();
}
}
resultList=newArrayList(result);
returnresultList;
}
/**
*@方法描述:获取两个ArrayList的交集
*@paramfirstArrayList第一个ArrayList
*@paramsecondArrayList第二个ArrayList
*@returnresultList交集ArrayList
*/
publicstaticListreceiveCollectionList(ListfirstArrayList,ListsecondArrayList){
ListresultList=newArrayList();
LinkedListresult=newLinkedList(firstArrayList);//大集合用linkedlist
HashSetothHash=newHashSet(secondArrayList);//小集合用hashset
Iteratoriter=result.iterator();//采用Iterator迭代器进行数据的操作
while(iter.hasNext()){
if(!othHash.contains(iter.next())){
iter.remove();
}
}
resultList=newArrayList(result);
returnresultList;
}
/**
*@方法描述:获取两个ArrayList的去重并集
*@paramfirstArrayList第一个ArrayList
*@paramsecondArrayList第二个ArrayList
*@returnresultList去重并集ArrayList
*/
publicstaticListreceiveUnionList(ListfirstArrayList,ListsecondArrayList){
ListresultList=newArrayList();
SetfirstSet=newTreeSet(firstArrayList);
for(Stringid:secondArrayList){
//当添加不成功的时候说明firstSet中已经存在该对象
firstSet.add(id);
}
resultList=newArrayList(dawjidSet);
returnresultList;
}
}
打印结果:
===================差集=================== aaa ddd ===================交集=================== bbb ccc =================去重并集================== aaa bbb ccc ddd eee
说明,取差集指的是取firstArrayList中存在但secondArrayList中不存在的数据集
以上这篇java较大数据量取差集,list.removeAll性能优化详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。