如何从两个List中筛选出相同的值

问题
现有社保卡和身份证若干,想要匹配筛选出一一对应的社保卡和身份证。
转换为List<社保卡> socialList,和List idList,从二者中找出匹配的社保卡。
模型
创建社保卡类
/**
* @author Ryan Miao
*/
class SocialSecurity{
private Integer id;//社保号码
private Integer idCard;//身份证号码
private String somethingElse;
public SocialSecurity(Integer id, Integer idCard, String somethingElse) {
this.id = id;
this.idCard = idCard;
this.somethingElse = somethingElse;
}
public Integer getId() {
return id;
}
public Integer getIdCard() {
return idCard;
}
public String getSomethingElse() {
return somethingElse;
}
@Override
public String toString() {
return "SocialSecurity{" +
"id=" + id +
", idCard=" + idCard +
", somethingElse='" + somethingElse + '\'' +
'}';
}
}
创建身份证类
class IdCard {
private Integer id;//身份证号码
private String somethingElse;
public IdCard(Integer id, String somethingElse) {
this.id = id;
this.somethingElse = somethingElse;
}
public Integer getId() {
return id;
}
public String getSomethingElse() {
return somethingElse;
}
@Override
public String toString() {
return "IdCard{" +
"id=" + id +
", somethingElse='" + somethingElse + '\'' +
'}';
}
}
最简单的办法:遍历
只要做两轮循环即可。
准备初始化数据:
private ArrayList<SocialSecurity> socialSecurities;
private ArrayList<IdCard> idCards;
@Before
public void setUp(){
socialSecurities = Lists.newArrayList(
new SocialSecurity(1, 12, "小明"),
new SocialSecurity(2, 13, "小红"),
new SocialSecurity(3, 14, "小王"),
new SocialSecurity(4, 15, "小peng")
);
idCards = Lists.newArrayList(
new IdCard(14, "xiaopeng"),
new IdCard(13, "xiaohong"),
new IdCard(12, "xiaoming")
);
//目标: 从socialSecurities中筛选出idCards中存在的卡片
}
遍历
@Test
public void testFilterForEach(){
List<SocialSecurity> result = new ArrayList<>();
int count = 0;
for (SocialSecurity socialSecurity : socialSecurities) {
for (IdCard idCard : idCards) {
count++;
if (socialSecurity.getIdCard().equals(idCard.getId())){
result.add(socialSecurity);
}
}
}
System.out.println(result);
System.out.println(count);//12 = 3 * 4
//O(m,n) = m*n;
}
很容易看出,时间复杂度O(m,n)=m*n.
采用Hash
通过观察发现,两个list取相同的部分时,每次都遍历两个list。那么,可以把判断条件放入Hash中,判断hash是否存在来代替遍历查找。
@Test
public void testFilterHash(){
Set<Integer> ids = idCards
.stream()
.map(IdCard::getId)
.collect(Collectors.toSet());
List<SocialSecurity> result = socialSecurities
.stream()
.filter(e->ids.contains(e.getIdCard()))
.collect(Collectors.toList());
System.out.println(result);
//初始化 hash 3
//遍历socialSecurities 4
//从hash中判断key是否存在 4
//O(m,n)=2m+n=11
}
如此,假设hash算法特别好,hash的时间复杂度为O(n)=n。如此推出这种做法的时间复杂度为O(m,n)=2m+n. 当然,更重要的是这种写法更让人喜欢,天然不喜欢嵌套的判断,喜欢扁平化的风格。
Hash一定会比遍历快吗
想当然的以为,hash肯定会比遍历快,因为是hash啊。其实,可以算算比较结果。比较什么时候2m+n < m*n。
从数据归纳法的角度,n必须大于2,不然即演变程2m+2 < 2m。于是,当n>2时:
@Test
public void testCondition(){
int maxN = 0;
for (int m = 2; m < 100; m++) {
for (int n = 3; n < 100; n++) {
if ((2*m+n)>m*n){
System.out.println("m="+m +",n="+n);
if (n>maxN){
maxN = n;
}
}
}
}
System.out.println(maxN);
}
结果是:
m=2,n=3
3
也就是说n<=3的时候,遍历要比hash快。事实上还要更快,因为hash还需要创建更多的对象。然而,大部分情况下,n也就是第二个数组的长度是大于3的。这就是为什么说hash要更好写。当然,另一个很重要的原因是lambda stream的运算符号远比嵌套循环让人喜爱。
如何从两个List中筛选出相同的值的更多相关文章
- js下拉框:从数组中筛选出匹配的数据
handleChange(val) { let obj = {} // 遍历数组 obj = this.options.find(item => { // 筛选出匹配的数据 return ite ...
- 【java小工具】从.java文件中筛选出方法,并计算出方法在这些文件中出现的次数
package getMethod; import java.io.*; import java.util.*; import java.util.regex.Matcher; import java ...
- 使用pandas筛选出指定列值所对应的行
在pandas中怎么样实现类似mysql查找语句的功能: select * from table where column_name = some_value; pandas中获取数据的有以下几种方法 ...
- 选取两个有序数组中最大的K个值,降序存入另一个数组中
原题: 假设有两个有序的整型数组int *a1, int *a2,长度分别为m和n.试用C语言写出一个函数选取两个数组中最大的K个值(K可能大于m+n)写到int *a3中,保持a3降序,并返回a3实 ...
- Leetcode33--->Search in Rotated Sorted Array(在旋转数组中找出给定的target值的位置)
题目: 给定一个旋转数组,但是你不知道旋转位置,在旋转数组中找出给定target值出现的位置:你可以假设在数组中没有重复值出现 举例: (i.e., 0 1 2 4 5 6 7 might becom ...
- JS函数 编程练习 使用javascript代码写出一个函数:实现传入两个整数后弹出较大的整数。
编程练习 使用javascript代码写出一个函数:实现传入两个整数后弹出较大的整数. 任务 第一步: 编写代码完成一个函数的定义吧. 第二步: 我们来补充函数体中的控制语句,完成函数功能吧. 提示: ...
- 键相同,比较两个map中的值是否相同
获取.排序.比较两个Map中相同key对应value值 /** * * @param hashMap 原数据 * @param hashMap2 需要比较的数据 * @return */ privat ...
- 【452】pandas筛选出表中满足另一个表所有条件的数据
参考:pandas筛选出表中满足另一个表所有条件的数据 参考:pandas:匹配两个dataframe 使用 pd.merge 来实现 on 表示查询的 columns,如果都有 id,那么这是很好的 ...
- Java - Collection 高效的找出两个List中的不同元素
如题:有List<String> list1和List<String> list2,两个集合各有上万个元素,怎样取出两个集合中不同的元素? 方法1:遍历两个集合 public ...
随机推荐
- 最大流isap模板
isap+bfs初始化+栈优化,点的编号从0开始: ; ; const int INF = 0x3f3f3f3f; struct Edge { int to, next, cap, flow; }ed ...
- Unix硬链接和符号链接(转)
首先要弄清楚,在Linux系统中,内核为每一个新创建的文件分配一个Inode(索引结点),每个文件都有一个惟一的inode号.文件属性保存在索引结点里,在访问文件时,索引结点被复制到内存在,从而实现文 ...
- Just for Today
Just for today I will try to live through this day only and not tackle my whole life problem at once ...
- Django编写RESTful API(三):基于类的视图
欢迎访问我的个人网站:www.comingnext.cn 前言 在上一篇文章中,主要讲的是请求和响应,项目里面views.py中的视图函数都是基于函数的,并且我们介绍了@api_view这个很有用的装 ...
- 给你的网站免费配置上 HTTPS 证书
现在越来越多的网站或服务增加了 HTTPS 证书,苹果 AppStore.微信小程序等也已强制要求开发者需提供 HTTPS 的后端接口.在阿里云 / 腾讯云上有一年期的免费赛门铁克 SSL 证书可供尝 ...
- Git学习总结(一)
.常用Git命令清单 一.新建代码库 #在当前目录创建一个Git代码库 $ git init #新建一个目录,将其初始化为Git代码库 $ git init [project name] #下载一个项 ...
- SSL证书:Web加密使互联网更安全
在网络安全的圈子里,我们都会隔三差五的听到某某公司遭受恶意软件攻击.或大量的隐私信息被泄露等等事件,此类安全事件往往都有影响范围广.涉及用户众多等特点.不免让人质疑联网的世界越来越危险.然而,在安全专 ...
- Java笔记—— 格式化的输入和输出
精确输出 可以用8个字符的宽度和小数点后了两个字符的精度打印x. double x = 10000.0 /3.0; System.out.printf("%8.2f\n",x);/ ...
- Ubuntu下安装NVIDIA显卡驱动的教训
今天在ubuntu16.04版本下安装了NVIDIA的显卡驱动,真的是一波十六折: 首先是在英伟达的官网上查找你自己电脑的显卡型号然后下载相应的驱动. 网址:http://www.nvidia.cn/ ...
- shell脚本编程基础
最近学习了shell脚本编程,感觉自己的脚本写的不太好,所以想把shell脚本相关的知识系统的整理一下,便于以后的学习和使用. 一.shell脚本基础 shell脚本是利用shell的功能 ...