如何从两个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 ...
随机推荐
- The C++ Programming Language 学习笔记 第6章 表达式和语句
1.关于strcpy函数. 书中说c风格的字符串尽量少用,strcpy这样的函数应该也要少用.这里讲这个函数主要是要通过本章课后练习第十题来讲一下前面提及的要点.巩固一下前几章的知识.写了一段,本来感 ...
- [2016-07-15]结合命令行工具awk和多行文本编辑器快速生成DataSeed代码
目标:根据业务提供的两份数据,生成DataSeed代码 SampleDataA 上海 华东一线 上饶 华东四线 中山 华南二线 临汾 华北四线 临沂 华东二线 SampleDataB 上海 1D04E ...
- IO库
IO类 C++语言不直接处理出入输出,而是通过一族定义在标准库中的类型来处理IO.这些类型支持从设备读取数据.向设备写入数据的IO操作,设备可以是文件 .控制台窗口 等.还有一些类型允许内存IO ,即 ...
- Tomcat启动:Container StandardContext[] has not been started
Container StandardContext[] has not been started\root.xml 初始化失败,检查数据源配置
- sed修炼系列(四):sed中的疑难杂症
本文目录:1 sed中使用变量和变量替换的问题2 反向引用失效问题3 "-i"选项的文件保存问题4 贪婪匹配问题5 sed命令"a"和"N" ...
- [js高手之路]深入浅出webpack教程系列7-( babel-loader,css-loader,style-loader)的用法
什么是loader呢,官方解释为文件的预处理器,通俗点说webpack在处理静态资源的时候,需要加载各种loader,比如,html文件,要用html-loader, css文件要用css-loade ...
- 关于小程序http请求的问题
解决wx.request 发起的是 HTTPS 请求的问题 对于wx.request,大家可以理解为是微信小程序版的ajax,基于安全性考虑他的url地址必须是以https开头的,但对于一个开发者来说 ...
- 最近做了一个通达OA的大料:20170905最新版本破解可改单位名称,无限制安装
最近做了一个通达OA的大料:20170905最新版本破解可改单位名称,无限制安装 用户约七十家,总体不错,修改了两次注册授权文件,完美使用中 可联系麦枫http://www.mfsun.com管理员Q ...
- ★电车难题的n个坑爹变种
哲学家都不会做的电车难题变异 此题会答清华北大 "电车难题(Trolley Problem)"是伦理学领域最为知名的思想实验之一,其内容大致是: 一个疯子把五个无辜的人绑在电车轨道 ...
- 【Alpha】Daily Scrum Meeting——Day4
站立式会议照片 1.本次会议为第四次Meeting会议: 2.本次会议在大课间09:40,在图书馆一楼楼道召开,本次会议为30分钟讨论昨天的任务完成情况以及接下来的任务安排. 燃尽图 每个人的工作分配 ...