Java中List集合对象去重及按属性去重的8种方法

您所在的位置:网站首页 重的生肖属性 Java中List集合对象去重及按属性去重的8种方法

Java中List集合对象去重及按属性去重的8种方法

2024-07-11 09:15:55| 来源: 网络整理| 查看: 265

一、本文描述

这一篇文章写一下List集合元素去重的8种方法,实际上通过灵活的运用、排列组合不一定是8种,可能有18种方法。

对象元素整体去重的4种方法按照对象属性去重的4种方法

为了在下文中进行测试内容讲解,我们先做一些初始化数据

public class ListRmDuplicate { private List list; private List playerList; @BeforeEach public void setup() { list = new ArrayList(); list.add("kobe"); list.add("james"); list.add("curry"); list.add("zimug"); list.add("zimug"); playerList= new ArrayList(); playerList.add(new Player("kobe","10000")); //科比万岁 playerList.add(new Player("james","32")); playerList.add(new Player("curry","30")); playerList.add(new Player("zimug","27")); // 注意这里名字重复 playerList.add(new Player("zimug","18")); //注意这里名字和年龄重复 playerList.add(new Player("zimug","18")); //注意这里名字和年龄重复 } }

Player对象就是一个普通的java对象,有两个成员变量name与age,实现了带参数构造函数、toString、equals和hashCode方法、以及GET/SET方法。

二、集合元素整体去重

下文中四种方法对List中的String类型以集合元素对象为单位整体去重。如果你的List放入的是Object对象,需要你去实现对象的equals和hashCode方法,去重的代码实现方法和List去重是一样的。

第一种方法

是大家最容易想到的,先把List数据放入Set,因为Set数据结构本身具有去重的功能,所以再将SET转为List之后就是去重之后的结果。这种方法在去重之后会改变原有的List元素顺序,因为HashSet本身是无序的,而TreeSet排序也不是List种元素的原有顺序。

@Test void testRemove1() { /*Set set = new HashSet(list); List newList = new ArrayList(set);*/ //去重并排序的方法(如果是字符串,按字母表排序。如果是对象,按Comparable接口实现排序) //List newList = new ArrayList(new TreeSet(list)); //简写的方法 List newList = new ArrayList(new HashSet(list)); System.out.println( "去重后的集合: " + newList); }

控制台打印结果如下:

去重后的集合: [kobe, james, zimug, curry]

第二种方法

使用就比较简单,先用stream方法将集合转换成流,然后distinct去重,最后在将Stream流collect收集为List。

@Test void testRemove2() { List newList = list.stream().distinct().collect(Collectors.toList()); System.out.println( "去重后的集合: " + newList); }

控制台打印结果如下:

去重后的集合: [kobe, james, curry, zimug]

第三种方法

这种方法利用了set.add(T),如果T元素已经存在集合中,就返回false。利用这个方法进行是否重复的数据判断,如果不重复就放入一个新的newList中,这个newList就是最终的去重结果

//三个集合类list、newList、set,能够保证顺序 @Test void testRemove3() { Set set = new HashSet(); List newList = new ArrayList(); for (String str :list) { if(set.add(str)){ //重复的话返回false newList.add(str); } } System.out.println( "去重后的集合: " + newList); }

控制台打印结果和第二种方法一致。

第四种方法

这种方法已经脱离了使用Set集合进行去重的思维,而是使用newList.contains(T)方法,在向新的List添加数据的时候判断这个数据是否已经存在,如果存在就不添加,从而达到去重的效果。

//优化 List、newList、set,能够保证顺序 @Test void testRemove4() { List newList = new ArrayList(); for (String cd:list) { if(!newList.contains(cd)){ //主动判断是否包含重复元素 newList.add(cd); } } System.out.println( "去重后的集合: " + newList); }

控制台打印结果和第二种方法一致。

三、按照集合元素对象属性去重

其实在实际的工作中,按照集合元素对象整体去重的应用的还比较少,更多的是要求我们按照元素对象的某些属性进行去重。 看到这里请大家回头去看一下上文中,构造的初始化数据playerList,特别注意其中的一些重复元素,以及成员变量重复。

第一种方法

为TreeSet实现Comparator接口,如果我们希望按照Player的name属性进行去重,就去在Comparator接口中比较name。下文中写了两种实现Comparator接口方法:

lambda表达式:(o1, o2) -> o1.getName().compareTo(o2.getName())方法引用:Comparator.comparing(Player::getName) @Test void testRemove5() { //Set playerSet = new TreeSet((o1, o2) -> o1.getName().compareTo(o2.getName())); Set playerSet = new TreeSet(Comparator.comparing(Player::getName)); playerSet.addAll(playerList); /*new ArrayList(playerSet).forEach(player->{ System.out.println(player.toString()); });*/ //将去重之后的结果打印出来 new ArrayList(playerSet).forEach(System.out::println); }

输出结果如下:三个zimug因为name重复,另外两个被去重。但是因为使用到了TreeSet,list中元素被重新排序。

Player{name=‘curry’, age=‘30’} Player{name=‘james’, age=‘32’} Player{name=‘kobe’, age=‘10000’} Player{name=‘zimug’, age=‘27’}

第二种方法

这种方法是网上很多的文章中用来显示自己很牛的方法,但是在笔者看来有点脱了裤子放屁,多此一举。既然大家都说有这种方法,我不写好像我不牛一样。我为什么说这种方法是“脱了裤子放屁”?

首先用stream()把list集合转换成流然后用collect及toCollection把流转换成集合然后剩下的就和第一种方法一样了

前两步不是脱了裤子放屁么?看看就得了,实际应用意义不大,但是如果是为了学习Stream流的使用方法,搞出这么一个例子还是有可取之处的。

@Test void testRemove6() { List newList = playerList.stream().collect(Collectors .collectingAndThen( Collectors.toCollection(() -> new TreeSet(Comparator.comparing(Player::getName))), ArrayList::new)); newList.forEach(System.out::println); }

控制台打印输出和第一种方法一样。

第三种方法

这种方法也是笔者建议大家使用的一种方法,咋一看好像代码量更大了,但实际上这种方法是应用比较简单的方法。

Predicate(有人管这个叫断言,从英文的角度作为名词可以翻译为谓词,作为动词可以翻译为断言)。谓词就是用来修饰主语的,比如:喜欢唱歌的小鸟,喜欢唱歌就是谓词,用来限定主语的范围。所以我们这里是用来filter过滤的,也是用来限制主语范围的,所以我认为翻译为谓词更合适。随便吧,看你怎么觉得怎么理解合理、好记,你就怎么来。

首先我们定义一个谓词Predicate用来过滤,过滤的条件是distinctByKey。谓词返回ture元素保留,返回false元素被过滤掉。当然我们的需求是过滤掉重复元素。我们去重逻辑是通过map的putIfAbsent实现的。putIfAbsent方法添加键值对,如果map集合中没有该key对应的值,则直接添加,并返回null,如果已经存在对应的值,则依旧为原来的值。如果putIfAbsent返回null表示添加数据成功(不重复),如果putIfAbsent返回value(value==null :false),则满足了distinctByKey谓词的条件元素被过滤掉。

这种方法虽然看上去代码量增大了,但是distinctByKey谓词方法只需要被定义一次,就可以无限复用。

@Test void testRemove7() { List newList = new ArrayList(); playerList.stream().filter(distinctByKey(p -> p.getName())) //filter保留true的值 .forEach(newList::add); newList.forEach(System.out::println); } static Predicate distinctByKey(Function keyExtractor) { Map seen = new ConcurrentHashMap(); //putIfAbsent方法添加键值对,如果map集合中没有该key对应的值,则直接添加,并返回null,如果已经存在对应的值,则依旧为原来的值。 //如果返回null表示添加数据成功(不重复),不重复(null==null :TRUE) return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; }

输出结果如下:三个zimug因为name重复,另外两个被去重。并且没有打乱List的原始顺序

Player{name=‘kobe’, age=‘10000’} Player{name=‘james’, age=‘32’} Player{name=‘curry’, age=‘30’} Player{name=‘zimug’, age=‘27’}

第四种方法

第四种方法实际上不是新方法,上面的例子都是按某一个对象属性进行去重,如果我们想按照某几个元素进行去重,就需要对上面的三种方法进行改造。 我只改造其中一个,另外几个改造的原理是一样的,就是把多个比较属性加起来,作为一个String属性进行比较。

@Test void testRemove8() { Set playerSet = new TreeSet(Comparator.comparing(o -> (o.getName() + "" + o.getAge()))); playerSet.addAll(playerList); new ArrayList(playerSet).forEach(System.out::println); } 总结

到此这篇关于Java中List集合对象去重及按属性去重的8种方法的文章就介绍到这了



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭