当前位置: 首页 > news >正文

东光网站建设淘宝店铺装修/快速排名点击工具

东光网站建设淘宝店铺装修,快速排名点击工具,贵阳论坛网站建设,营销型公司网站java8 列表通过 stream流 根据对象属性去重的三种实现方法 一、简单去重 public class DistinctTest {/*** 没有重写 equals 方法*/SetterGetterToStringAllArgsConstructorNoArgsConstructorpublic static class User {private String name;private Integer age;}/*** lombo…

java8 列表通过 stream流 根据对象属性去重的三种实现方法

一、简单去重

public class DistinctTest {/*** 没有重写 equals 方法*/@Setter@Getter@ToString@AllArgsConstructor@NoArgsConstructorpublic static class User {private String name;private Integer age;}/*** lombok(@Data) 重写了 equals 方法 和 hashCode 方法*/@Data@AllArgsConstructor@NoArgsConstructorpublic static class User2 {private String name;private Integer age;}@Testpublic void easyTest() {List<Integer> integers = Arrays.asList(1, 1, 2, 3, 4, 4, 5, 6, 77, 77);System.out.println("======== 数字去重 =========");System.out.print("原数字列表:");integers.forEach(x -> System.out.print(x + " "));System.out.println();System.out.print("去重后数字列表:");integers.stream().distinct().collect(Collectors.toList()).forEach(x -> System.out.print(x + " "));System.out.println();System.out.println();List<User> list = Lists.newArrayList();User three = new User("张三", 18);User three2 = new User("张三", 18);User three3 = new User("张三", 24);User four = new User("李四", 18);list.add(three);list.add(three);list.add(three2);list.add(three3);list.add(four);System.out.println("======== 没有重写equals方法的话,只能对相同对象(如:three)进行去重,不能做到元素相同就可以去重) =========");// 没有重写 equals 方法时,使用的是超类 Object 的 equals 方法// 等价于两个对象 == 的比较,只能筛选同一个对象System.out.println("初始对象列表:");list.forEach(System.out::println);System.out.println("简单去重后初始对象列表:");list.stream().distinct().collect(Collectors.toList()).forEach(System.out::println);System.out.println();System.out.println();List<User2> list2 = Lists.newArrayList();User2 five = new User2("王五", 18);User2 five2 = new User2("王五", 18);User2 five3 = new User2("王五", 24);User2 two = new User2("二蛋", 18);list2.add(five);list2.add(five);list2.add(five2);list2.add(five3);list2.add(two);System.out.println("======== 重写了equals方法的话,可以做到元素相同就可以去重) =========");// 所以如果只需要写好 equals 方法 和 hashCode 方法 也能做到指定属性的去重System.out.println("初始对象列表:");list2.forEach(System.out::println);System.out.println("简单去重后初始对象列表:");list2.stream().distinct().collect(Collectors.toList()).forEach(System.out::println);}
}

二、根据对象某个属性去重

0、User对象

    /*** 没有重写 equals 方法*/@Setter@Getter@ToString@AllArgsConstructor@NoArgsConstructorpublic static class User {private String name;private Integer age;}

1、使用filter进行去重

    @Testpublic void objectTest() {List<User> list = Arrays.asList(new User(null, 18),new User("张三", null),null,new User("张三", 24),new User("张三5", 24),new User("李四", 18));System.out.println("初始对象列表:");list.forEach(System.out::println);System.out.println();System.out.println("======== 使用 filter ,根据特定属性进行过滤(重不重写equals方法都不重要) =========");System.out.println("根据名字过滤后的对象列表:");// 第一个 filter 是用于过滤 第二个 filter 是用于去重List<User> collect = list.stream().filter(o -> o != null && o.getName() != null).filter(distinctPredicate(User::getName)).collect(Collectors.toList());collect.forEach(System.out::println);System.out.println("根据年龄过滤后的对象列表:");List<User> collect1 = list.stream().filter(o -> o != null && o.getAge() != null).filter(distinctPredicate(User::getAge)).collect(Collectors.toList());collect1.forEach(System.out::println);}/*** 列表对象去重*/public <K, T> Predicate<K> distinctPredicate(Function<K, T> function) {// 因为stream流是多线程操作所以需要使用线程安全的ConcurrentHashMapConcurrentHashMap<T, Boolean> map = new ConcurrentHashMap<>();return t -> null == map.putIfAbsent(function.apply(t), true);}
测试

在这里插入图片描述

①、疑惑

既然 filter 里面调用的是 distinctPredicate 方法,而该方法每次都 new 一个新的 map 对象,那么 map 就是新的,怎么能做到可以过滤呢

②、解惑

先看一下 filter 的部分实现逻辑,他使用了函数式接口 Predicate ,每次调用filter时,会使用 predicate 对象的 test 方法,这个对象的test 方法就是 null == map.putIfAbsent(function.apply(t), true)

而 distinctPredicate 方法作用就是生成了一个线程安全的 Map 集合,和一个 predicate 对象,且该对象的 test 方法为 null == map.putIfAbsent(function.apply(t), true)

之后 stream 流的 filter 方法每次都只会使用 predicate 对象的 test 方法,而该 test 方法中的 map 对象在该流中是唯一的,并不会重新初始化

    @Overridepublic final Stream<P_OUT> filter(Predicate<? super P_OUT> predicate) {Objects.requireNonNull(predicate);return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,StreamOpFlag.NOT_SIZED) {@OverrideSink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {@Overridepublic void begin(long size) {downstream.begin(-1);}@Overridepublic void accept(P_OUT u) {if (predicate.test(u))downstream.accept(u);}};}};}

2、使用Collectors.toMap() 实现根据某一属性去重(这个可以实现保留前一个还是后一个)

要注意 Collectors.toMap(key,value) 中 value 不能为空,会报错,key 可以为 null,但会被转换为字符串的 “null”

    @Testpublic void objectTest() {List<User> list = Arrays.asList(new User(null, 18),new User("张三", null),null,new User("张三", 24),new User("张三5", 24),new User("李四", 18));System.out.println("初始对象列表:");list.forEach(System.out::println);System.out.println();System.out.println("======== 使用 Collectors.toMap() 实现根据某一属性去重 =========");System.out.println("根据名字过滤后的对象列表 写法1:");// (v1, v2) -> v1 的意思 两个名字一样的话(key一样),存前一个 value 值Map<String, User> collect = list.stream().filter(Objects::nonNull).collect(Collectors.toMap(User::getName, o -> o, (v1, v2) -> v1));// o -> o 也可以写为 Function.identity() ,两个是一样的,但后者可能比较优雅,但阅读性不高,如下// Map<String, User> collect = list.stream().filter(Objects::nonNull).collect(Collectors.toMap(User::getName, Function.identity(), (v1, v2) -> v1));List<User> list2 = new ArrayList<>(collect.values());list2.forEach(System.out::println);System.out.println("根据名字过滤后的对象列表 写法2:");Map<String, User> map2 = list.stream().filter(o -> o != null && o.getName() != null).collect(HashMap::new, (m, o) -> m.put(o.getName(), o), HashMap::putAll);list2 = new ArrayList<>(map2.values());list2.forEach(System.out::println);System.out.println("根据年龄过滤后的对象列表:");// (v1, k2) -> v2 的意思 两个年龄一样的话(key一样),存后一个 value 值Map<Integer, User> collect2 = list.stream().filter(Objects::nonNull).collect(Collectors.toMap(User::getAge, o -> o, (v1, v2) -> v2));list2 = new ArrayList<>(collect2.values());list2.forEach(System.out::println);}
测试

在这里插入图片描述

2.2、Collectors.toMap() 的变种 使用 Collectors.collectingAndThen()

Collectors.collectingAndThen() 函数 它可接受两个参数,第一个参数用于 reduce操作,而第二参数用于 map操作。

也就是,先把流中的所有元素传递给第一个参数,然后把生成的集合传递给第二个参数来处理。

@Testpublic void objectTest() {List<User> list = Arrays.asList(new User(null, 18),new User("张三", null),null,new User("张三", 24),new User("张三5", 24),new User("李四", 18));System.out.println("初始对象列表:");list.forEach(System.out::println);System.out.println();System.out.println("======== 使用 Collectors.toMap() 实现根据某一属性去重 =========");System.out.println("根据名字过滤后的对象列表:");ArrayList<User> collect1 = list.stream().filter(o -> o != null && o.getName() != null).collect(Collectors.collectingAndThen(Collectors.toMap(User::getName, o -> o, (k1, k2) -> k2), x-> new ArrayList<>(x.values())));collect1.forEach(System.out::println);System.out.println("======== 或者 ==========");List<User> collect = list.stream().filter(o -> o != null && o.getName() != null).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))), ArrayList<User>::new));collect.forEach(System.out::println);}
测试

在这里插入图片描述

三、测试哪个方法比较快

    @Testpublic void objectTest() {List<User> list = new ArrayList<>(Arrays.asList(new User(null, 18),new User("张三", null),null,new User("张三", 24),new User("张三5", 24),new User("李四", 18)));for (int i = 0; i < 100000; i++) {list.add(new User((Math.random() * 10) + "", (int) (Math.random() * 10)));}System.out.println("======== 测试速度 =========");long startTime = System.currentTimeMillis();List<User> list1 = list.stream().filter(o -> o != null && o.getName() != null).filter(distinctPredicate(User::getName)).collect(Collectors.toList());long endTime = System.currentTimeMillis();System.out.println("filter 用时 :" + (endTime - startTime));System.out.println();startTime = System.currentTimeMillis();Map<String, User> map1 = list.stream().filter(o -> o != null && o.getName() != null).collect(Collectors.toMap(User::getName, o -> o, (v1, v2) -> v1));List<User> list2 = new ArrayList<>(map1.values());endTime = System.currentTimeMillis();System.out.println("map1 用时 :" + (endTime - startTime));System.out.println();startTime = System.currentTimeMillis();ArrayList<User> list3 = list.stream().filter(o -> o != null && o.getName() != null).collect(Collectors.collectingAndThen(Collectors.toMap(User::getName, o -> o, (k1, k2) -> k2), x -> new ArrayList<>(x.values())));endTime = System.currentTimeMillis();System.out.println("map2 用时 :" + (endTime - startTime));System.out.println();startTime = System.currentTimeMillis();List<User> list4 = list.stream().filter(o -> o != null && o.getName() != null).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))), ArrayList<User>::new));endTime = System.currentTimeMillis();System.out.println("map3 用时 :" + (endTime - startTime));System.out.println();startTime = System.currentTimeMillis();Map<String, User> map2 = list.stream().filter(o -> o != null && o.getName() != null).collect(HashMap::new, (m, o) -> m.put(o.getName(), o), HashMap::putAll);List<User> list5 = new ArrayList<>(map2.values());endTime = System.currentTimeMillis();System.out.println("map4 用时 :" + (endTime - startTime));}

测试:

在这里插入图片描述

四、结论

1、去重最快:

	ArrayList<User> list3 = list.stream().filter(o -> o != null && o.getName() != null).collect(Collectors.collectingAndThen(Collectors.toMap(User::getName, o -> o, (k1, k2) -> k2), x -> new ArrayList<>(x.values())));// 或者Map<String, User> map2 = list.stream().filter(o -> o != null && o.getName() != null).collect(HashMap::new, (m, o) -> m.put(o.getName(), o), HashMap::putAll);List<User> list5 = new ArrayList<>(map2.values());

2、其次

        Map<String, User> map1 = list.stream().filter(o -> o != null && o.getName() != null).collect(Collectors.toMap(User::getName, o -> o, (v1, v2) -> v1));List<User> list2 = new ArrayList<>(map1.values());// distinctPredicate 是一个方法 本文中有 ,可以 ctrl + f 查找List<User> list1 = list.stream().filter(o -> o != null && o.getName() != null).filter(distinctPredicate(User::getName)).collect(Collectors.toList());

3、最慢

	List<User> list4 = list.stream().filter(o -> o != null && o.getName() != null).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))), ArrayList<User>::new));

相关文章:

java8 列表通过 stream流 根据对象属性去重的三种实现方法

java8 列表通过 stream流 根据对象属性去重的三种实现方法 一、简单去重 public class DistinctTest {/*** 没有重写 equals 方法*/SetterGetterToStringAllArgsConstructorNoArgsConstructorpublic static class User {private String name;private Integer age;}/*** lombo…...

鸿蒙开发DevEco Studio Setup 工具认识及使用

1、界面认识 1.1 创建页面之前理解Ability 1.2 理解stage模式 1.3 工程级别目录结构 1.4 模块级别目录...

程序员裁员潮:技术变革下的职业危机

程序员裁员潮&#xff1a;技术变革下的职业危机 一对来自中国的工程师夫妻在美身亡&#xff0c;疑因谷歌裁员致悲剧发生。在技术变革下&#xff0c;裁员对于程序员的影响到底有多大&#xff1f;快来和我们分享一下你的看法吧~ 哎&#xff0c;这是悲哀&#xff0c;让我又想起来…...

Cesium快速入门

文章目录 0.引言1.Cesium环境搭建1.1安装Node.js环境1.2配置Cesium依赖 2.搭建第一个Cesium程序2.1引入源码编译结果2.2创建html文件2.3编写第一个Cesium程序2.4申请许可密钥2.5发布Cesium程序服务 3.界面介绍4.默认控件介绍 0.引言 现有的gis开发方向较流行的是webgis开发&am…...

Android.mk和Android.bp的区别和转换详解

Android.mk和Android.bp的区别和转换详解 文章目录 Android.mk和Android.bp的区别和转换详解一、前言二、Android.mk和Android.bp的联系三、Android.mk和Android.bp的区别1、语法&#xff1a;2、灵活性&#xff1a;3、版本兼容性&#xff1a;4、向后兼容性&#xff1a;5、编译区…...

卡尔曼滤波器原理By_DR_CAN 学习笔记

DR_CAN卡尔曼滤波器 Kalman Filter Recursive Algorithm迭代过程 数学基础正态分布和6-SigmaData FusionCovariance MatrixState Space Representation离散化推导 linearizationTaylor Series2-DSummary Step by Step Derivation of Kalman Gain矩阵求导公式 Prior / Posterio…...

013 异常

文章目录 异常人为创造异常 异常 定义:运行时检测的错误 try:可能触发异常的语句 except 错误类型1 [as 变量1]:处理语句1 except 错误类型2:处理语句2 except Exception:不是以上错误类型的处理语句 else:未发生异常的语句 finally:无论是否发生异常的语句异常处理:保障程序…...

微服务Spring Cloud架构详解

"Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具&#xff08;例如配置管理&#xff0c;服务发现&#xff0c;断路器&#xff0c;智能路由&#xff0c;微代理&#xff0c;控制总线&#xff09;。分布式系统的协调导致了样板模式, 使用Spring Cloud开…...

推荐一一款小众黑科技工具,低调使用建议收藏

wireshark是个啥就不多说了&#xff0c;非常流行的网络封包分析软件。 可以截取各种网络封包&#xff0c;显示网络封包的详细信息。 软件功能十分强大&#xff0c;操作也不复杂。 很多小友都在后台问能不能出一期完整的抓包分析贴&#xff0c;今天给你们安排上了哈。 01 W…...

HiP框架:多AI模型联手,助力机器人驾驭复杂规划大局

原创 | 文 BFT机器人 你的日常待办清单或许只是些稀松平常的小事&#xff1a;清洗堆积如山的碗盘、采购琳琅满目的食品杂货等。在执行这些任务时&#xff0c;你无需逐一写下“捧起那只满是油污的盘子”或“用湿润的海绵仔细擦洗这个盘子”这样的琐碎步骤&#xff0c;因为在你的…...

关于OC中变量相关知识点

众所周知&#xff0c;变量是用来存储数据的 围绕着变量&#xff0c;有很多知识点&#xff0c;总结归纳一下 变量的类型变量的作用区域局部变量全局变量静态变量变量的访问范围属性成员变量实例变量synthesizedynamic… 变量的类型 变量大致分为两大类型&#xff1a; 基本数据…...

机器学习分类模型评价指标总结(准确率、精确率、召回率、Fmax、TPR、FPR、ROC曲线、PR曲线,AUC,AUPR)

为了看懂论文&#xff0c;不得不先学一些预备知识&#xff08;&#xff08;55555 主要概念 解释见图 TP、FP、TN、FN 准确率、精确率&#xff08;查准率&#xff09;、召回率&#xff08;查全率&#xff09; 真阳性率TPR、伪阳性率FPR F1-score2TP/(2*TPFPFN) 最大响应分…...

go语言(十一)----面向对象继承

一、面向对象继承 写一个父类 package mainimport "fmt"type Human struct {name stringsex string }func (this *Human) Eat() {fmt.Println("Human.Eat()...") }func (this *Human) Walk() {fmt.Println("Human.Walk()...") }func main() {h…...

一款自动化提权工具

免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删除。…...

【Qt】最详细教程,如何从零配置Qt Android安卓环境

这里写自定义目录标题 安装Qt Creator & Qt安装下载&安装JDK设置Android SDKAndroid模拟器下载创建android设备&#xff08;模拟器&#xff09; Gradle安装问题解决无法打开安卓模拟器Build失败方案一&#xff1a;不适用Qt自带SDK管理器&#xff08;失败&#xff09;方…...

spring与spring boot的区别

spring与spring boot的区别 项目配置&#xff1a; Spring&#xff1a; 在Spring中&#xff0c;项目的配置通常需要在XML文件中进行&#xff0c;包括配置数据源、事务管理、AOP等。这需要开发人员手动配置很多细节。 <!-- 在Spring中使用XML配置数据源 --> <bean id…...

http网络编程——在ue5中实现文件传输功能

http网络编程在ue5中实现 需求&#xff1a;在unreal中实现下载功能&#xff0c;输入相关url网址&#xff0c;本地文件夹存入相应文件。 一、代码示例 1.Build.cs需要新增Http模块&#xff0c;样例如下。 PublicDependencyModuleNames.AddRange(new string[] { "Core&q…...

JVM之java内存区域[2](堆、方法区、直接内存)

文章目录 版权声明一 堆1.1 java堆1.2 模拟堆区的溢出1.3 arthas中堆内存相关的功能1.4 设置大小 二 方法区2.1 方法区简介2.2 补充&#xff1a;字符串常量池和运行时常量池2.3 方法区的大小设计2.4 arthas中查看方法区2.5 模拟方法区的溢出2.7 StringTable的练习题 三 神奇的i…...

k8s-kubectl常用命令

一、基础命令 1.1 get 查询集群所有资源的详细信息&#xff0c;resource包括集群节点、运行的Pod、Deployment、Service等。 1.1.1 查询Pod kubectl get po -o wid 1.1.2 查询所有NameSpace kubectl get namespace 1.1.3 查询NameSpace下Pod kubectl get po --all-namespaces…...

如何在Docker上运行Redis

环境: 1.windows系统下的Docker deckstop 1.Pull Redis镜像 2.运行Redis镜像 此时,Redis已经启动&#xff0c;我们登录IDEA查看下是否连接上了 显示连接成功&#xff0c;证明已经连接上Docker上的Redis了...

【深度学习:集中偏差】减少计算机视觉数据集中偏差的 5 种方法

【深度学习&#xff1a;集中偏差】减少计算机视觉数据集中偏差的 5 种方法 有偏差的计算机视觉数据集会导致哪些问题&#xff1f;如何减少计算机视觉数据集中偏差的示例观察并监控带注释样本的类别分布确保数据集代表模型适用的人群明确定义对象分类、标记和注释的流程为标签质…...

java数据结构与算法刷题-----LeetCode667. 优美的排列 II

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 题目要求我们返回一个数组长度为n的数组&#xff0c;必须含有1~n…...

win10 20h2 defender添加排除项失败怎么回事 Window Defender添加不了排除项如何处理

我们都知道win10系统中是内置有Windows Defender安全防护软件的&#xff0c;会自动对电脑中的所有文件进行扫描&#xff0c;但是有用户可能某些文件不希望被扫描&#xff0c;那么我们可以添加排除项&#xff0c;可是有不少win10 20h2用户在defender添加排除项的时候却失败了&am…...

mysql生成最近24小时整点时间临时表

文章目录 生成最近24小时整点生成最近30天生成最近12个月 生成最近24小时整点 SELECT-- 每向下推1行, i比上次减去1b.*, i.*,DATE_FORMAT( DATE_SUB( NOW(), INTERVAL ( -( i : i - 1 ) ) HOUR ), %Y-%m-%d %H:00 ) AS time FROM-- 目的是生成12行数据( SELECTa FROM( SELECT…...

基于PHP反序列化练习

PHP创建一个以自己姓名命名的类&#xff0c;要求存在两个属性&#xff0c;name&#xff0c;age&#xff0c;进行序列化&#xff0c;输出序列化以后的数据。 <!-- PHP创建一个以自己姓名命名的类&#xff0c;要求存在两个属性&#xff0c;name&#xff0c;age --> <?…...

ITSS、ITIL、ISO20000:哪个更适合你?

在IT服务管理领域&#xff0c;ITSS、ITIL和ISO20000是备受关注的三大标准。它们在性质、设立组织、目的和适用对象等方面各有千秋。那么&#xff0c;如何在这三大标准中选择最适合自己的呢&#xff1f;下面&#xff0c;让我们一起揭开它们的神秘面纱&#xff01; 1️⃣ 性质&am…...

Linux配置yum源以及基本yum指令

文章目录 一、yum介绍二、什么是软件包三、配置yum源四、一键配置yum源【三步走】五、yum指令搜索软件安装软件卸载软件 六、其他yum指令更新内核更新软件更新指定软件显示所有可更新的软件清单卸载指定包并自动移除依赖包删除软件包&#xff0c;以及软件包数据和配置文件 一、…...

【AI视野·今日Robot 机器人论文速览 第七十五期】Thu, 11 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Thu, 11 Jan 2024 Totally 16 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Analytical Model and Experimental Testing of the SoftFoot: an Adaptive Robot Foot for Walking over Obstacles and Irre…...

阿里云ECS(CentOS镜像)安装docker

目录 1.前置条件 2.连接至ECS 3.yum软件包更新 4.安装docker前置所需软件包 5.添加docker 官方的 yum 软件源 6.安装docker 7.检测是否成功 8.配置阿里云镜像加速器 1.前置条件 在看本文前保证未安装过docker,或者安装过但是清理干净 如果多次安装失败过&#xff0c;…...

服务器工作环境要求

在开展网站服务之前&#xff0c;合适的服务器工作环境是必不可少的。服务器工作环境指需要一定的软硬件条件来保障服务器可以正常地运转和提供高效率的服务。在这篇文章中&#xff0c;我们将会详细讲解服务器工作环境所需的要素。 一、硬件要求 服务器硬件方面包括了基本的电…...