Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何从两个List中筛选出相同的值

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

作者头像
Ryan-Miao
发布于 2018-03-14 02:26:57
发布于 2018-03-14 02:26:57
6.5K00
代码可运行
举报
文章被收录于专栏:Ryan MiaoRyan Miao
运行总次数:0
代码可运行

问题

现有社保卡和身份证若干,想要匹配筛选出一一对应的社保卡和身份证。 转换为List<社保卡> socialList,和List idList,从二者中找出匹配的社保卡。

模型

创建社保卡类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @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 + '\'' +
                '}';
    }
}

创建身份证类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 + '\'' +
                '}';
    }
}

最简单的办法:遍历

只要做两轮循环即可。 准备初始化数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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中存在的卡片
}

遍历

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 @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是否存在来代替遍历查找。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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时:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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);
}

结果是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
m=2,n=3
3

也就是说n<=3的时候,遍历要比hash快。事实上还要更快,因为hash还需要创建更多的对象。然而,大部分情况下,n也就是第二个数组的长度是大于3的。这就是为什么说hash要更好写。当然,另一个很重要的原因是lambda stream的运算符号远比嵌套循环让人喜爱。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
原型模式以及克隆技术
原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
java技术爱好者
2020/09/22
4330
Java基础——Set接口
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/details/51272846
DannyHoo
2018/09/13
4280
Java基础——Set接口
【SSH快速进阶】——Hibernate一对一映射(one-to-one)——唯一外键关联
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/details/50253847
DannyHoo
2018/09/13
5500
【SSH快速进阶】——Hibernate一对一映射(one-to-one)——唯一外键关联
java之hibernate之基于外键的双向一对一关联映射
这篇讲解 基于外键的双向一对一关联映射 1.考察如下信息,人和身份证之间是一个一对一的关系。表的设计 2.类结构 Person.java public class Person implements
Vincent-yuan
2019/09/11
7800
java之hibernate之基于外键的双向一对一关联映射
java8新特性stream().map().collect()用法
List idcards=new ArrayList();//定义一个集合来装身份证号码
瑞新
2020/12/07
3K0
【SSH快速进阶】——Hibernate一对一映射(one-to-one)——主键关联映射
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/details/50219961
DannyHoo
2018/09/13
6160
【SSH快速进阶】——Hibernate一对一映射(one-to-one)——主键关联映射
Java EE之SSM框架整合开发 -- (7) MyBatis映射器
2.在MyBatis中针对不同的数据库软件,<insert>元素如何将主键回填?
浩Coding
2019/07/03
2.5K0
图解设计模式: 有趣的工厂模式
在工厂模式中 父子类的关系就像是生产工厂中模具一样, 由父类负责指定实例生成的方式 子类来决定生成具体的类. 具体的处理全部交给子类负责,目的就是为了将生产实例的框架和负责实例生产类解耦
冷环渊
2022/12/20
3650
图解设计模式: 有趣的工厂模式
面试官:请讲一下MyBatis是如何关联关系?
在关系型数据库中,多表之间存在着三种关联关系,分别为一对一、一对多和多对多,如下图所示:
千羽
2021/12/29
7430
面试官:请讲一下MyBatis是如何关联关系?
MatchTitle 主程序入口
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/105944.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/09
8030
Java小技能:快速创建List常用几种方式
本文主要介绍collection接口下的List接口和Set接口,以及迭代器Iterator。
公众号iOS逆向
2022/12/19
4.1K0
Java小技能:快速创建List常用几种方式
23种设计模式(四) —— 手写实现 Factory Method 模式 (将具体交给子类)
该模式用于生成实例,Factory 是工厂,用 Template Method 模式来构建生成实例的工厂。
Gorit
2021/12/08
3850
23种设计模式(四) —— 手写实现 Factory Method 模式 (将具体交给子类)
Java8使用stream操作两个list根据某字段匹配再对其中一个list进行赋值
import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; @Slf4j public class ListUtils { /** * lambda表达式对两个List进行循环,根据符合条件,进行相关的赋值操作并
JavaEdge
2021/12/07
5K0
SpringBoot使用validator校验
在前台表单验证的时候,通常会校验一些数据的可行性,比如是否为空,长度,身份证,邮箱等等,那么这样是否是安全的呢,答案是否定的。因为也可以通过模拟前台请求等工具来直接提交到后台,比如postman这样的
dalaoyang
2018/06/13
6730
微服务项目:尚融宝(36)(核心业务流程:用户绑定(1))
尚融宝应该在网站引导客户在“资金托管平台“开设账户。也就是说投资人和借款人必须在资金托管平台页面上自主开户,与尚融宝建立对应的账户体系。
一个风轻云淡
2022/11/15
2900
微服务项目:尚融宝(36)(核心业务流程:用户绑定(1))
php中时间戳等相关小概念笔记
首先说下时间戳吧,因为工作需要,对接接口时要用到各种类型的时间戳,所以抽个时间把这些时间戳整理了下. 如果想看看返回的时间戳对不对,这里有个在线转换工具,可以试试时间戳在线转换
仇诺伊
2018/09/12
1.4K0
基于Feign初探Ranger Api
在大数据平台之权限管理组件 - Aapche Ranger一文中我们了解了Ranger以及安装部署过程以及Admin可视化界面的使用。
端碗吹水
2020/11/13
9631
基于Feign初探Ranger Api
Java8 Stream使用flatMap合并List
之前也写过很多篇关于Java8使用的文章了,但是回顾一下,好像还没介绍过Java8 Stream的flatMap操作,昨天刚好在工作中遇到一个场景,发现flatMap简直太方便了,这里总结一下flatMap的常规使用。附带讲一下,使用Java8实现集合的并、交、差操作,其实之前也讲过一种使用Guava的实现方式,具体请参考Guava集合工具
全栈程序员站长
2022/09/05
5.7K0
Java8学习(4)-Stream流
Stream和Collection的区别是什么 流和集合的区别是什么? 粗略地说, 集合和流之间的差异就在于什么时候进行计算。集合是一个内存中的数据结构,它包含数据结构中目前所有的值--集合中的每个元素都得先计算出来才能添加到内存里。(你可以往集合里加东西或者删东西,但是不管什么时候,集合中的每个元素都是放在内存里的,元素都得计算出来才能成为集合的一部分。) 相比之下,流则是在概念上固定的数据结构(你不能添加或者删除元素),其元素则是按需计算的。这对编程有很大的好处。用户仅仅从流中提取需要的值,而这
Ryan-Miao
2018/04/17
1.7K0
Java8学习(4)-Stream流
MybatisFlex关联查询
在 MyBatis-Flex 中,提供了 4 个 Relations 注解,他们分别是:
流年Felix
2023/09/05
8231
推荐阅读
相关推荐
原型模式以及克隆技术
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验