java 较大数据量取差集,list.removeAll性能优化详解

作者:_Jason_PC_ 时间:2022-11-06 16:52:15 

今天在优化项目中的考勤同步功能时遇到将考勤机中的数据同步到数据库,

两边都是几万条数据的样子,老代码的做法差不多半个小时,优化后我本机差不多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()),而无需关注下标的问题

改进代码


 LinkedList linkedList= new LinkedList(src);//大集合用linkedlist
HashSet hashSet= new HashSet(oth);//小集合用hashset
Iterator iter = linkedList.iterator();//采用Iterator迭代器进行数据的操作
while(iter.hasNext()){
if(hashSet.contains(iter.next())){
iter.remove();
}
}

补充知识:JAVA获取两个数据量较大的ArrayList的交集、差集以及并集

测试说明:获取firstArrayList和secondArrayList的交集、差集以及并集。实际测试中firstArrayList数据量190000,secondArrayList数据量170000.效率比较高。此处只列出少量数据。测试代码如下:


import java.util.Set;
import java.util.List;
import java.util.HashSet;
import java.util.TreeSet;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.LinkedList;

public class getSet {

public static void main(String args[]) {
 getList();
}

// 获取两个ArrayList的差集、交集、去重并集(数据量大小不限制)
private static void getList() {
 List<String> firstArrayList = new ArrayList<String>();
 List<String> secondArrayList = new ArrayList<String>();
 List<String> defectList = new ArrayList<String>();//差集List
 List<String> collectionList = new ArrayList<String>();//交集List
 List<String> unionList = new ArrayList<String>();//去重并集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);
  Iterator<String> defectIterator = defectList.iterator();
  System.out.println("===================差集===================");
  while(defectIterator.hasNext()) {
   System.out.println(defectIterator.next());
  }
  // 获取交集
  collectionList = receiveCollectionList(firstArrayList, secondArrayList);
  Iterator<String> collectionIterator = collectionList.iterator();
  System.out.println("===================交集===================");
  while(collectionIterator.hasNext()) {
   System.out.println(collectionIterator.next());
  }
  // 获取去重并集
  unionList = receiveUnionList(firstArrayList, secondArrayList);
  Iterator<String> unionIterator = unionList.iterator();
  System.out.println("===================去重并集===================");
  while(unionIterator.hasNext()) {
   System.out.println(unionIterator.next());
  }
 }catch(Exception e) {
  e.printStackTrace();
 }
}

/**
 * @方法描述:获取两个ArrayList的差集
 * @param firstArrayList 第一个ArrayList
 * @param secondArrayList 第二个ArrayList
 * @return resultList 差集ArrayList
 */
public static List<String> receiveDefectList(List<String> firstArrayList, List<String> secondArrayList) {
 List<String> resultList = new ArrayList<String>();
 LinkedList<String> result = new LinkedList<String>(firstArrayList);// 大集合用linkedlist
 HashSet<String> othHash = new HashSet<String>(secondArrayList);// 小集合用hashset
 Iterator<String> iter = result.iterator();// 采用Iterator迭代器进行数据的操作
 while(iter.hasNext()){
  if(othHash.contains(iter.next())){
   iter.remove();  
  }  
 }
 resultList = new ArrayList<String>(result);
 return resultList;
}

/**
 * @方法描述:获取两个ArrayList的交集
 * @param firstArrayList 第一个ArrayList
 * @param secondArrayList 第二个ArrayList
 * @return resultList 交集ArrayList
 */
public static List<String> receiveCollectionList(List<String> firstArrayList, List<String> secondArrayList) {
 List<String> resultList = new ArrayList<String>();
 LinkedList<String> result = new LinkedList<String>(firstArrayList);// 大集合用linkedlist
 HashSet<String> othHash = new HashSet<String>(secondArrayList);// 小集合用hashset
 Iterator<String> iter = result.iterator();// 采用Iterator迭代器进行数据的操作
 while(iter.hasNext()) {
  if(!othHash.contains(iter.next())) {
   iter.remove();  
  }  
 }
 resultList = new ArrayList<String>(result);
 return resultList;
}

/**
 * @方法描述:获取两个ArrayList的去重并集
 * @param firstArrayList 第一个ArrayList
 * @param secondArrayList 第二个ArrayList
 * @return resultList 去重并集ArrayList
 */
public static List<String> receiveUnionList(List<String> firstArrayList, List<String> secondArrayList) {
 List<String> resultList = new ArrayList<String>();
 Set<String> firstSet = new TreeSet<String>(firstArrayList);
 for(String id : secondArrayList) {
  // 当添加不成功的时候 说明firstSet中已经存在该对象
  firstSet.add(id);
 }
 resultList = new ArrayList<String>(dawjidSet);
 return resultList;
}
}

打印结果:


===================差集===================
aaa
ddd
===================交集===================
bbb
ccc
=================去重并集==================
aaa
bbb
ccc
ddd
eee

说明,取差集指的是取firstArrayList中存在但secondArrayList中不存在的数据集

来源:https://blog.csdn.net/u013675978/article/details/86620411

标签:java,数据,差集,list.removeAll,优化
0
投稿

猜你喜欢

  • 关于SpringSecurity配置403权限访问页面的完整代码

    2023-11-13 02:03:59
  • Android开发中ImageLoder进行图片加载和缓存

    2023-08-18 10:14:30
  • Android仿微信朋友圈添加图片的实例代码

    2021-06-26 13:19:05
  • spring boot 2整合swagger-ui过程解析

    2021-08-08 22:57:35
  • 从"Show tabs"了解Android Input系统

    2023-12-21 05:20:49
  • java去除空格、标点符号的方法实例

    2021-12-01 16:16:42
  • 在编码时如何使用\\r与\\n,两者的区别

    2023-04-08 11:19:00
  • 详解flutter中常用的container layout实例

    2022-07-25 07:49:53
  • 在Eclipse中运行Solr 基础知识

    2021-07-06 22:51:04
  • Tomcat内存溢出分析及解决方法

    2023-11-12 23:24:47
  • Java实现浪漫流星表白的示例代码

    2023-04-02 14:50:35
  • C++实现LeetCode(5.最长回文子串)

    2023-07-03 06:07:13
  • Java基础之位运算知识总结

    2022-09-10 17:48:43
  • 关于C#结构体 你需要知道的

    2022-01-04 13:11:49
  • C语言中的回调函数实例

    2021-09-27 08:37:12
  • mybatis如何实现saveOrUpdate

    2021-07-18 10:33:11
  • c#使用Unity粒子实现炮塔发射系统

    2023-11-04 19:05:19
  • Spring Boot基础学习之Mybatis操作中使用Redis做缓存详解

    2023-01-19 16:35:55
  • MyBatis图文并茂讲解注解开发多对多查询

    2022-10-27 17:05:04
  • SpringCloud灾难性雪崩效应处理方法之降级实现流程详解

    2022-03-24 15:31:36
  • asp之家 软件编程 m.aspxhome.com