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()),而无需关注下标的问题

改进代码

  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中不存在的数据集

以上这篇java 较大数据量取差集,list.removeAll性能优化详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • IntelliJ IDEA里找不到javax.servlet的jar包的解决方法

    今天在复习Java Web时,因为初次使用 IntelliJ IDEA 中, 当使用javax.servlet包下的类时(例:javax.servlet.http.HttpServletRequest), 你会发现在IntelliJ IDEA里无法成功编译这个程序. 问题解决: 办法1:使用Project Structure 在弹出的窗口中选择tomcat所在的目录,进入里面的lib目录,寻找servlet-api.jar这个jar包(如果JSP页面也有相关的JavaWeb对象,则还要寻找jsp

  • 解决dubbo错误ip及ip乱入问题的方法

    问题 在本地启动dubbo时,服务注册在本地的zookeeper ,但是注册IP却不是本地的iP.产生问题,导致consumer 找不到provider ,访问不了服务. 例如 本地IP为 10.0.0.1 ,但是zookeeper上的注册ip 可能是 196.168.0.1 产生原因,随机产生,可能是你重启一下机器,或者电脑小智一段时间就会发生. 报错类似 com.alibaba.dubbo.remoting.RemotingException: client(url: dubbo://100

  • Java 获取两个List的交集和差集,以及应用场景操作

    背景介绍 在实际项目中,特别是一些管理后台类的项目,会遇到底层数据是按照一对多关系的数据表存储的管理界面.列表页是一对多关系中一对应的数据列表,二级的详情页中是一对多关系中多对应的多条数据展示.通常二级页面是能够增.删.改数据的编辑页面,在点击保存提交数据后,服务器端需要插入新增的数据,删除要删除的数据,更新改变的数据. 例如,在汽车电商领域,如果要实现一辆车型在不同省份有不同的价格行情,就需要有一个车价管理的后台管理界面.每辆车对应的详情界面管理各省价格行情,增加该车在某个省份的行情,或者更新

  • 如何解决IDEA使用Tomcat控制台中文出现乱码问题

    如下图所示,Intellij IDEA显示中文为乱码, 根据Intellij IDEA控制台输出,Tomcat Log出现乱码,因此可以将问题定位到Tomcat上,具体解决方法: 第一步:打开Tomcat安装位置,找到:conf下的logging.properties文件,然后右击使用文本编辑器打开. 第二步:把这五个UTF-8都改为:GBK 改好后如下图所示. 之后重启tomcat后在看控制台输出,中文就没有乱码了,成功解决! 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支

  • 为什么程序中突然多了 200 个 Dubbo-thread 线程的说明

    背景 在某次查看程序线程堆栈信息时,偶然发现有 200 个 Dubbo-thread 线程,而且大部分都处于 WAITING 状态,如下所示: "Dubbo-thread-200" #160932 daemon prio=5 os_prio=0 tid=0x00007f5af9b54800 nid=0x79a6 waiting on condition [0x00007f5a9acd5000] java.lang.Thread.State: WAITING (parking) at s

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

    今天在优化项目中的考勤同步功能时遇到将考勤机中的数据同步到数据库, 两边都是几万条数据的样子,老代码的做法差不多半个小时,优化后我本机差不多40秒,服务器速度会更加理想. 两个数据集取差集首先想到的方法便是List.removeAll方法,但是实验发现jdk自带的List.removeAll效率很低 List.removeAll效率低原因: List.removeAll效率低和list集合本身的特点有关 : List底层数据结构是数组,查询快,增删慢 1.List.contains()效率没有h

  • MySQL Limit性能优化及分页数据性能优化详解

    MySQL Limit可以分段查询数据库数据,主要应用在分页上.虽然现在写的网站数据都是千条级别,一些小的的优化起的作用不大,但是开发就要做到极致,追求完美性能.下面记录一些limit性能优化方法. Limit语法: SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset LIMIT子句可以被用于强制 SELECT 语句返回指定的记录数.LIMIT接受一个或两个数字参数.参数必须是一个整数常量. 如果给定两个参数,第一个参数指定

  • MySQL 大数据量快速插入方法和语句优化分享

    锁定也将降低多连接测试的整体时间,尽管因为它们等候锁定最大等待时间将上升.例如: 复制代码 代码如下: Connection 1 does 1000 inserts Connections 2, 3, and 4 do 1 insert Connection 5 does 1000 inserts 如果不使用锁定,2.3和4将在1和5前完成.如果使用锁定,2.3和4将可能不在1或5前完成,但是整体时间应该快大约40%. INSERT.UPDATE和DELETE操作在MySQL中是很快的,通过为在

  • Java实现excel大数据量导入

    本文实例为大家分享了Java实现excel大数据量导入的具体代码,供大家参考,具体内容如下 情景分析: 通常我们通过poi读取excel文件时,若在用户模式下,由于数据量较大.Sheet较多,很容易出现内存溢出的情况 用户模式读取excel的典型代码如下: FileInputStream file = new FileInputStream("c:\\test.xlsx"); Workbook wb=new XSSFWorkbook(file); 而03版(xls)excel文件每个s

  • Java使用POI导出大数据量Excel的方法

    今天需要写一个导出的Excel的功能,但是发现当数据量到3万条时,列数在23列时,内存溢出,CPU使用100%,测试环境直接炸掉.在本地测试时发现,导出3000条左右的数据的时候,堆内存瞬间升高500M左右.然后发现了 SXSSFWorkbook 这个类. 简介 SXSSFWorkbook 需要 poi-ooxml 包 3.8 及以上开始支持,我这边适使用的是 3.9 版本,本质是一个 XSSFWorkbook 类( Excel2007 ),它使用的方式是采用 硬盘空间 来大幅降低 堆内存 的占

  • 大数据量时提高分页的效率

    如我们在之前的教程里讨论的那样,分页可以通过两种方法来实现: 默认分页– 你仅仅只用选中data Web control的 智能标签的Enable Paging ; 然而,当你浏览页面的时候,虽然你看到的只是一小部分数据,ObjectDataSource 还是会每次都读取所有数据 自定义分页– 通过只从数据库读取用户需要浏览的那部分数据,提高了性能. 显然这种方法需要你做更多的工作. 默认的分页功能非常吸引人,因为你只需要选中一个checkbox就可以完成了.但是它每次都读取所有的数据,这种方式

  • 在ASP.NET 2.0中操作数据之二十五:大数据量时提高分页的效率

    导言 如我们在之前的教程里讨论的那样,分页可以通过两种方法来实现: 1.默认分页– 你仅仅只用选中data Web control的 智能标签的Enable Paging ; 然而,当你浏览页面的时候,虽然你看到的只是一小部分数据,ObjectDataSource 还是会每次都读取所有数据 2.自定义分页– 通过只从数据库读取用户需要浏览的那部分数据,提高了性能. 显然这种方法需要你做更多的工作. 默认的分页功能非常吸引人,因为你只需要选中一个checkbox就可以完成了.但是它每次都读取所有的

  • python pickle存储、读取大数据量列表、字典数据的方法

    先给大家介绍下python pickle存储.读取大数据量列表.字典的数据 针对于数据量比较大的列表.字典,可以采用将其加工为数据包来调用,减小文件大小 #列表 #存储 list1 = [123,'xiaopingguo',54,[90,78]] list_file = open('list1.pickle','wb') pickle.dump(list1,list_file) list_file.close() #读取 list_file = open('list1.pickle','rb')

  • 解决Mybatis 大数据量的批量insert问题

    前言 通过Mybatis做7000+数据量的批量插入的时候报错了,error log如下: , ('G61010352', '610103199208291214', '学生52', 'G61010350', '610103199109920192', '学生50', '07', '01', '0104', ' ', , ' ', ' ', current_timestamp, current_timestamp ) 被中止,呼叫 getNextException 以取得原因. at org.p

  • 关于使用OpenCsv导入大数据量报错的问题

    导入100W的Csv数据,使用OpenCsv解析工具解析Csv,发现报错 报错内容 com.opencsv.exceptions.CsvMalformedLineException: Unterminated quoted field at end of CSV line. Beginning of lost text: [XXXXX...]  at com.opencsv.CSVReader.readNext(CSVReader.java:355) ~[opencsv-4.6.jar!/:na

随机推荐