List根据属性去重

创建一个user集合

 User user1 = new User("user1", 18, "AAA");
User user2 = new User("user2", 18, "BBB");
User user3 = new User("user3", 18, "AAA");
User user4 = new User("user4", 75, "CCC");
User user5 = new User("user5", 35, "AAA"); ArrayList<User> list = new ArrayList<>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
list.add(user5);

自定义Predict函数,使用filter()

写一个Predict
public class DistinctKeyUtil {
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
}
使用filter方法
/**
* 写一个Predict进行属性过滤
*/
//先过滤age在过滤hobby
List<User> result = list.stream()
.filter(DistinctKeyUtil.distinctByKey(n -> n.getAge()))
.filter(DistinctKeyUtil.distinctByKey(n -> n.getHobby()))
.collect(Collectors.toList()); result.forEach(System.out::println);
结果:
User{name='user1', age=18, hobby='AAA'}
User{name='user4', age=75, hobby='CCC'}
小结:

实质上是将每个元素都放到distinctByKey()中的ConcurrentHashMap作为key进行过滤,如果key不存在那么就加上去,如果已经存在了就不加。所以这种方式的过滤只保留第一个重复元素。

利用TreeSet

        //过滤age
ArrayList<User> result2 = list.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(o -> o.getAge()))), ArrayList::new)); result2.forEach(System.out::println);

结果与上面的一样

同时过滤两个属性

        //age和hobby一起过滤
ArrayList<User> result1 = list.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(o -> o.getHobby() + ";" + o.getAge()))), ArrayList::new)
);
result1.forEach(System.out::println);
结果:
User{name='user1', age=18, hobby='AAA'}
User{name='user5', age=35, hobby='AAA'}
User{name='user2', age=18, hobby='BBB'}
User{name='user4', age=75, hobby='CCC'}
小结:

TreeSet存储唯一的元素,并且按升序对元素进行排序。

Map:保证Key的唯一性

        /**
* map 根据某属性过滤
*/
// Function.identity() 相等于 o->o
Map<String, User> map1 = list.stream().collect(Collectors.toMap(User::getHobby, Function.identity(), (t1, t2) -> t1));
Set<Map.Entry<String, User>> entries1 = map1.entrySet();
entries1.forEach(System.out::println);
结果:
AAA=User{name='user1', age=18, hobby='AAA'}
CCC=User{name='user4', age=75, hobby='CCC'}
BBB=User{name='user2', age=18, hobby='BBB'}
小结:

map可以选择保留重复属性中的前一条数据还是后一条:(t1, t2) -> t1)

Stream流根据属性去重的更多相关文章

  1. JDK 8 中Stream流中的去重的方法

    JDK 8 中Stream流中去重的方法 1.简单的去重,可以使用distinct()方法去重,该方法是通过比较equals和hashcode值去去重, 2.复杂的去重, 例如,在一个JavaBean ...

  2. 【JDK8】JDK 8 中Stream流中的去重的方法

    JDK 8 中Stream流中去重的方法 1.简单的去重,可以使用distinct()方法去重,该方法是通过比较equals和hashcode值去去重, 2.复杂的去重, 例如,在一个JavaBean ...

  3. Stream流用于按照对象中某一属性来对集合去重+简单数据类型集合的去重

    上次对Stream流来进行分组的文章很多人看,想看的可以来这: Stream流来进行集合分组 这次小编又带来Stream的去重,话不多数,直接上代码: 这是对简单数据类型的去重 //字符串集合进行简单 ...

  4. List使用Stream流进行集合Collection的各种运算汇总:对BigDecimal求和,某个字段的和、最大值、最小值、平均值,字段去重,过滤等

    写Java接口的朋友都知道,Java 8的更新,经常会用到过滤 list<Object> 里的数据,本文就对List使用Stream流进行集合Collection的各种运算做一个汇总! 优 ...

  5. (六)jdk8学习心得之Stream流

    六.Stream流 1. 什么是stream流 现阶段,可以把stream流看成一个高级版的Iterator.普通的Iterator只能实现遍历,遍历做什么,就需要具体些功能代码函数了.而这个stre ...

  6. 简洁方便的集合处理——Java 8 stream流

    背景 java 8已经发行好几年了,前段时间java 12也已经问世,但平时的工作中,很多项目的环境还停留在java1.7中.而且java8的很多新特性都是革命性的,比如各种集合的优化.lambda表 ...

  7. Java的Stream流式操作

    前言 最近在实习,在公司看到前辈的一些代码,发现有很多值得我学习的地方,其中有一部分就是对集合使用Stream流式操作,觉得很优美且方便.所以学习一下Stream流,在这里记录一下. Stream是什 ...

  8. 再来看看Java的新特性——Stream流

    半年前开始试着使用Java的新特性,给我印象最深的就是Stream流和Optional.其中Stream提高了看法效率,让代码看起来十分清爽. 为什么要使用流? 摘要中已经说明了,为了提高开发效率.流 ...

  9. 详解 stream流

    在本人之前的博文中,我们学习了 I/O流.NIO流的相关概念. 那么,在JDK8的更新内容中,提出了一个新的流 -- stream流 那么,现在,本人就来讲解下这个流: 目录 stream流 常用AP ...

  10. List集合对象去重及按属性去重的8种方法-java基础总结系列第六篇

    最近在写一些关于java基础的文章,但是我又不想按照教科书的方式去写知识点的文章,因为意义不大.基础知识太多了,如何将这些知识归纳总结,总结出优缺点或者是使用场景才是对知识的升华.所以我更想把java ...

随机推荐

  1. python内置函数len()

    len() len()函数用于返回对象(字符串.元组.列表和字典等)的长度或元素个数 len()函数的语法: len(s) 代码示例 print(len(range(10))) print(len([ ...

  2. VUE+.NET应用系统的国际化-多语言词条服务

    上篇文章我们介绍了 VUE+.NET应用系统的国际化-整体设计思路 系统国际化改造整体设计思路如下: 提供一个工具,识别前后端代码中的中文,形成多语言词条,按语言.界面.模块统一管理多有的多语言词条 ...

  3. Golang 实现 RTP

    在 Coding 之前我们先来简单介绍一下 RTP(Real-time Transport Protocol), 正如它的名字所说,用于互联网的实时传输协议,通过 IP 网络传输音频和视频的网络协议. ...

  4. Qt实用技巧:在CentOS上使用linuxdeployqt打包发布qt程序

    前言   之前在ubuntu上发布qt程序相对还好,使用脚本,在麒麟上发布的时候,使用脚本就不太兼容,同时为了实现直接点击应用可以启动应用的效果,使用linuxdeployqt发布qt程序.  本篇文 ...

  5. .Net 7 轻松上手Dapr之服务调用

    前言 对于Dapr ,在项目中也有用过一段时间,优缺点并存,但是瑕不掩瑜,目前随着版本的迭代和第三方团队对它的支持也使得我们用得更加得心应手,所以借此也回顾一下Dapr的相关知识以及分享一下项目中用到 ...

  6. vue之头像管理思路

    思路是在vant库中使用插件将上传的头像转码存入数据库中.每个用户存一个,不同用户就有不同的头像了.若数据库中没有头像,那么就给一个默认头像 头像上传后端接口: var express = requi ...

  7. kubernetes(k8s) 中安装kuboard面板

    kubernetes(k8s) 中安装kuboard面板 01 - 背景及安装 Kuboard 是一款专为 Kubernetes 设计的免费管理界面,兼容 Kubernetes 版本 1.13 及以上 ...

  8. 3.载荷和结果实体类以及Jwt

    1.昨天为了将两个项目推送到远程仓库,了解了一下分支,将一个小工程作为一个分支,这是发生在git add .,git commit -m "描述"以及git reomte add ...

  9. 基于Containerd容器引擎和kubeadm工具部署K8sv1.26.3

    前文我了解了基于ubuntu2204部署containerd容器引擎以及containerd客户端工具的部署和使用相关话题,回顾请参考:https://www.cnblogs.com/qiuhom-1 ...

  10. express获取登录服务器的IP地址

    let ip = (req.headers['x-real-ip'] || req.connection.remoteAddress).slice(7);