Java编程经验---比较两个List对象差异

2023-05-16

Java编程经验---比较两个List对象差异

  • 问题引入
  • 解决问题
    • 简化模型
      • 一般的办法
      • 速度更快的方法
      • Lambda表达式解决办法
  • 结语

问题引入

如何比较两个List对象的差异,这个问题来源于我最近正在开发的新系统中的一个细节。大致情况就是,从数据库中的一个视图A向另一个数据库的一张B表进行数据迁移。A的数据会随时更新,为了保证表B也可以及时获取数据,需要采用定时任务,不断同步数据。

每N分钟
视图A
表B

视图A中的数据在导入表B时,可能有数据已经在表B中,重复的导入浪费性能且可能发生潜在错误。那么就需要分析数据的差异后进行导入。先设一个前提,视图A与表B的结构相似,Primary Key为表中的某一单字段。

视图A示例

UserIdUserNameStatus
1MikeOK
2TrumpNO
3LiLiOK

表B示例

UserIdUserNameGender
1MikeMen
2TrumpWomen
5ChouMen

*这里的 UserId 时 Primery Key

解决问题

简化模型

我们可以先将问题简化为两个基本类型的List,举个最简单的例子就是两个List<int>

一般的办法

如何对比两个List的差异,最简单粗暴的当然就是使用两个for循环。

public static void main(String[] args) {
	int i = 0 ;
	//对比ListA和ListB的差异
	List<Integer> ListA = new LinkedList();
	List<Integer> ListB = new LinkedList();
	//获取相同的元素放入ListC
	List<Integer> ListC = new LinkedList();
	
	while( i<10000){
		ListA.add(i);
		i++;
	}
	i = 5;
	while( i<10005){
		ListB.add(i);
		i++;
	}
	
	//程序开始时间
	long st = System.nanoTime();
	//取得相同的元素
	for(int aIndex: ListA)
	{
		for(int bIndex: ListB)
		{
			if(aIndex == bIndex)
			{
				ListC.add(aIndex);
			}
		}
	}
	
	//分辨结束
	System.out.println("total times "+(System.nanoTime()-st));
	
	ListA.removeAll(ListC);
	ListB.removeAll(ListC);
	ListA.addAll(ListB);
	
	System.out.println(ListA.toString()); //打印差异元素
}

结果

total times 362768500
[0, 1, 2, 3, 4, 10000, 10001, 10002, 10003, 10004]

此时的算法复杂度为
O ( m × n ) O(m×n) O(m×n)

速度更快的方法

空间换时间

 public class Test {

	public static void main(String[] args) {
		int i = 0 ;
		//对比ListA和ListB的差异
		List<Integer> ListA = new LinkedList();
		List<Integer> ListB = new LinkedList();
		//获取相同的元素放入ListC
		List<Integer> ListC = new LinkedList();

		while( i<10000){
			ListA.add(i);
			i++;
		}
		i = 5;
		while( i<10005){
			ListB.add(i);
			i++;
		}
		
		Map<Integer,Integer> listMap = new HashMap();
		
		//程序开始时间
		long st = System.nanoTime();
		
		//取得相同的元素
		Iterator<Integer> iteratorA = ListA.iterator();
		while(iteratorA.hasNext())
		{
			Integer tempInteger = iteratorA.next(); 
			listMap.put(tempInteger.intValue(),tempInteger);
		}
		
		Iterator<Integer> iteratorB = ListB.iterator();
		while(iteratorB.hasNext())
		{
			Integer tempInteger = iteratorB.next(); 
			if(listMap.containsKey(tempInteger))
			{
				ListC.add(tempInteger);
			}
		}
		//分辨结束
		System.out.println("total times "+(System.nanoTime()-st));
		
		ListA.removeAll(ListC);
		ListB.removeAll(ListC);
		ListA.addAll(ListB);
		
		System.out.println(ListA.toString()); //打印差异元素
	}
}

结果

total times 2537200
[0, 1, 2, 3, 4, 10000, 10001, 10002, 10003, 10004]

做了一点改善,将原来的For循环用迭代来完成遍历,速度快了20%

此时的算法复杂度为
O ( m + n ) O(m+n) O(m+n)
很明显引入HashMap之后,算法复杂度大幅下降。这是由于在HashMap中查找元素的算法复杂度可以达到恐怖的O(1)。

特别说明
Java 8 之后,HashMap引入了红黑树存储,使得存储效率进一步提升,触发条件就是List长度大于8。

Lambda表达式解决办法

	public static void main(String[] args) {
		int i = 0 ;
		//对比ListA和ListB的差异
		List<Integer> ListA = new ArrayList();
		List<Integer> ListB = new ArrayList();
		//获取相同的元素放入ListC
		List<Integer> ListC = new ArrayList();

		while( i<10000){
			ListA.add(i);
			i++;
		}
		i = 5;
		while( i<10005){
			ListB.add(i);
			i++;
		}
		
		//程序开始时间
		long st = System.nanoTime();
		//取得相同的元素
		//采用Lambda表达式实现
		ListC = ListA.stream().filter(p -> ListB.contains((Integer)p)).collect(Collectors.toList());
		
		//分辨结束
		System.out.println("total times "+(System.nanoTime()-st));
		
		ListA.removeAll(ListC);
		ListB.removeAll(ListC);
		ListA.addAll(ListB);
		
		System.out.println(ListA.toString()); //打印差异元素
	}

先放结果吧

total times 41008300
[0, 1, 2, 3, 4, 10000, 10001, 10002, 10003, 10004]

总的来说还是要比第一种方法要快5,6倍,但是和使用HashMap还是有一定的差距。但是很明显语句非常的简洁。所以适当使用Lambda表达式可以使代码更加优雅。但是处理大量的数据时,效率不佳,不推荐。

结语

点滴积累,才能扎实成长。

时间有限,如有问题,及时更正。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java编程经验---比较两个List对象差异 的相关文章

随机推荐

  • cloudflare入门之 /cdn-cgi/ 端点

    1 简介 将域添加到 Cloudflare时 xff0c Cloudflare 会向该域添加一个 cdn cgi 端点 此端点由 Cloudflare 管理 它不能被修改或定制 一些使用此端点的例子包括 xff1a Cloudflare 机
  • cloudflare入门之附加 cookie

    文档 Cloudflare Cookies Cloudflare Fundamentals docs 1 简介 Cloudflare 使用 cookie 来最大化网络资源 管理流量并保护网站免受恶意流量的侵害 2 cflb 使用Cloudf
  • Linux入门之使用 ps 查看系统进程

    文档 PS Command ps command in Linux with Examples GeeksforGeeks ps 1 Linux manual page 1 简介 ps命令允许显示有关正在运行的进程的信息 它从 proc文件
  • Linux入门之使用 top 查看系统进程

    文档 Top command top command in Linux with Examples GeeksforGeeks top 1 Linux manual page 1 简介 top命令显示系统上正在运行的进程的实时列表 还显示有
  • android入门之使用 adb 进行屏幕截图

    文档 xff1a https developer android com studio command line adb screencap 1 进入shell adb shell shell 64 2 截图 在 shell 里进行截图 x
  • node.js实战之使用 jsdom

    文档 GitHub jsdom jsdom 1 简介 jsdom 是许多 web 标准的纯 JavaScript 实现 特别是 WHATWG DOM和HTML标准 该项目的目标是模拟足够多的 Web 浏览器子集 以用于测试和抓取真实世界的
  • CentOS-7 MySQL 5.7.20安装

    1 检查系统是否安装了mariadb rpm qa grep mariadb 发现已经安装 xff0c 卸载 rpm e nodeps mariadb libs 5 5 52 1 el7 x86 64 2 创建mysql用户组和mysql用
  • mac os入门之安装 brew

    nbsp 文档 The Missing Package Manager for macOS or Linux Homebrew 1 简介 Homebrew 安装了Apple 或 Linux 系统 不需要的东西 nbsp Homebrew 将
  • node.js入门之 mac os下安装 nvm

    1 安装 安装脚本与 linux 下一样 wget qO https raw githubusercontent com nvm sh nvm v0 39 1 install sh bash gt Downloading nvm from
  • make入门之编写 makefile

    文档 GNU make 1 简介 Makefile 包含五种内容 显式规则 隐式规则 变量定义 指令和注释 显式规则 何时及如何重新制作目标 列出了依赖的先决条件 提供创建或更新目标的配方 隐式规则 何时及如何根据文件名重新制作目标 描述如
  • 记一个 Nvidia Control Panel 打不开的问题

    1 简介 Nvidia Control Panel 打不开 xff0c 找到了应用点击没反应 2 解决 找到 NVIDIA Display Container LS 服务 xff0c 启动后 xff0c 右下角出现 NVIDIA 图标 右键
  • 记一个 Europe/Pari 时区冬令时从+2:00变成+1:00问题

    1 简介 代码里写死了时区 Europe Paris xff0c 而且时间点都是以文字时区为准 但是今天发现 xff0c 在本地对应的时间没有运行 最后发现 xff0c 之前Europe Paris 是 43 2 00 xff0c 早上10
  • android入门之 Support Library

    Use legacy support library option in android Stack Overflow https developer android com topic libraries support library
  • 记一个 react 配置路由前缀问题

    react 配置路由前缀需要注意两点 1 资源使用相对路径 默认情况下 xff0c react 编译后的资源使用根路径 xff0c 也就是长下面这样 lt script src 61 34 static js 2 dfc7d8c4 chun
  • nginx 配置SPA应用路由前缀

    1 配置 location xxx alias your directory try files uri uri xxx index html 路由匹配要使用 用 alias 改变当前目录 try files 的最后一个回退项目也必须有前缀
  • geckodriver selenium火狐浏览器驱动

    火狐浏览器驱动对浏览器版本没什么大的要求 xff0c 直接下载这个压缩包就可以 xff0c 在selenium使用中谷歌浏览器bug会很多 xff0c 并非网站反爬 xff0c 火狐或许可以解决 xff0c Releases mozilla
  • B站高清视频下载方法揭密

    有很多文章都介绍过B站的视频如何下载 xff0c 大部分介绍的都是如何通过第三方网站提供的工具下载 xff0c 使用起来有诸多不便 xff0c 也不能实现批量下载 xff0c 今天就给大家介绍一款命令行小工具 xff0c 保证让你爱不释手
  • Android 科大讯飞、语音听写集成指南

    前提说明 xff1a 讯飞SDK与appID xff08 后台申请 xff09 是一一对应的 否则就会导致初始化不成功 xff01 1 创建appID并下载SDK xff08 没有账号的先行注册 xff09 https console xf
  • MCU-51:单片机直流电机驱动(PWM)

    目录 一 直流电机介绍二 电机驱动电路三 PWM3 1 PWM介绍3 2 产生PWM方法 四 代码演示注意 xff1a 一定要看 一 直流电机介绍 直流电机是一种将电能转换为机械能的装置 一般的直流电机有两个电极 xff0c 当电极正接时
  • Java编程经验---比较两个List对象差异

    Java编程经验 比较两个List对象差异 问题引入解决问题简化模型一般的办法速度更快的方法Lambda表达式解决办法 结语 问题引入 如何比较两个List对象的差异 xff0c 这个问题来源于我最近正在开发的新系统中的一个细节 大致情况就