说道集合的去重,我们就肯定能想到唯一元素集合set,还有map中的key。那么我们传统的去重的方式肯定是要选择set或者是map来实现了,另外在对实体对象类型进行去重的时候,我们可能会指定实体中的一个字段,这种情况也是属于多数的,那么我们要怎么实现呢?

一、传统map实现

首先我们来看map实现,由于list内对象是不固定的,所以我这里写了一个通用的,按照id去重的例子:

/**
* 根据属性id去重
* @param objList 要去重的集合list
* @param <E> list内容泛型
* @return 返回去重后的list
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
public static <E> List<E> removeDuplicateId(List<E> objList) throws NoSuchFieldException, IllegalAccessException {
List<E> newList = new ArrayList<>();
HashMap<String, String> map = new HashMap<>();
for (E t : objList) {
// 为空则不进行比较(按需确定是否要添加)
if (org.springframework.util.StringUtils.isEmpty(getFieldValue(t,"id"))) {
continue;
}
String id = String.valueOf(getFieldValue(t,"id"));
String value = map.get(id);
if (org.springframework.util.StringUtils.isEmpty(value)) { //如果value是空的 说明取到的这个name是第一次取到
map.put(id, id);
newList.add(t); //newList就是我们想要的去重之后的结果
}
}
return newList;
}

当然这里还加入了一些自定义的配置,如字段为空的时候就舍弃等,可以看出来都是根据map特性,如果在map中找到了值,则不再add。

如果扩展成根据指定字段去重,则代码修改为把字段的string传入即可:

public static <E> List<E> removeDuplicateId(List<E> objList,String filedName) throws NoSuchFieldException, IllegalAccessException {

if (StringUtils.isBlank(filedName)){

return objList;

}

List<E> newList = new ArrayList<>();

HashMap<String, String> map = new HashMap<>();

for (E t : objList) {

// 为空则不进行比较(按需确定是否要添加)

if (org.springframework.util.StringUtils.isEmpty(getFieldValue(t,filedName))) {

continue;

}

String id = String.valueOf(getFieldValue(t,filedName));

String value = map.get(id);

if (org.springframework.util.StringUtils.isEmpty(value)) { //如果value是空的 说明取到的这个name是第一次取到

map.put(id, id);

newList.add(t); //newList就是我们想要的去重之后的结果

}

}

return newList;

}

如果要根据多个字段去重,需要怎样呢?扩展第二个参数为字符数组即可:

public static <E> List<E> removeDuplicateId(List<E> objList,String... filedNames) throws NoSuchFieldException, IllegalAccessException {

if (filedNames==null||filedNames.length==0){

return objList;

}

List<E> newList = new ArrayList<>();

HashMap<String, String> map = new HashMap<>();

for (E t : objList) {

String key = "";

for (int i = 0; i < filedNames.length; i++) {

key += String.valueOf(getFieldValue(t,filedNames[i]));

}

String value = map.get(key);

if (org.springframework.util.StringUtils.isEmpty(value)) { //如果value是空的 说明取到的这个name是第一次取到

map.put(key, key);

newList.add(t); //newList就是我们想要的去重之后的结果

}

}

return newList;

}

有了map的实现,set的也不难了,只需要把里面判断和添加map的代码修改为set对象即可。

二、labmda实现

lambda实现就比较简单了,看一下三连:

单个字段去重:

List<Member> memberList= members.stream() .collect(

Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(member -> member.getName()))), ArrayList::new));

多个字段去重:

List<Member> memberList = members.stream() .collect(

Collectors.collectingAndThen(

Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(member -> member.getName()+"-"+member.getId()))), ArrayList::new));

还有一个根据某个或者几个字段分组,也可以满足这种需求:

Map<String,List<Member>> map = members.stream().collect(Collectors.groupingBy(Member::getName));

三、总结

相比较来说,使用lambda进行去重,写法比较简单,代码简洁有利于阅读,而传统方式则过于繁琐,需要写专门的util进行处理,但是从另外的角度来讲传统方式比较灵活,可以增加lambda没有的判断,如果需要去重的字段有为null的情况,使用lambda分组或者去重是会报空指针错误的。

【java】对list集合进行去重 传统方式 VS Lambda的更多相关文章

  1. 练习:集合元素处理(传统方式)-练习:集合元素处理(Stream方式)

    练习:集合元素处理(传统方式) 题目 现在有两个ArrayList集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环依次进行以下若干操作步骤︰ 1.第一个队伍只要名字为3个字的 ...

  2. java中遍历集合的三种方式

    第一种遍历集合的方式:将集合变为数组 package com.lw.List; import java.util.ArrayList; import java.util.List; import ja ...

  3. Java遍历List集合的4种方式

    public class Test { public static void main(String[] args) { // 循环遍历List的4中方法 List<String> str ...

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

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

  5. paip.提高效率---集合的存取括号方式 uapi java python php js 的实现比较

    paip.提高效率---集合的存取括号方式 uapi java python php js 的实现比较 ##java ----------- 在JDK1.7中,摒弃了Java集合接口的实现类,如:Ar ...

  6. java List递归排序,传统方式和java8 Stream优化递归,无序的列表按照父级关系进行排序(两种排序类型)

    当有一个List列表是无序的,List中的数据有parentid进行关联,通过java排序成两种排序类型: 所用的测试列表最顶级无parentid,若为特殊值,修改下判断方法即可. 第一种排序:按照树 ...

  7. Java集合01----ArrayList的遍历方式及应用

                                                 Java集合01----ArrayList的遍历方式及应用 前面已经学习了ArrayList的源代码,为了学以 ...

  8. Java List集合 遍历 四种方式(包含 Lambda 表达式遍历)

    示例代码如下: package com.miracle.luna.lambda; import java.util.ArrayList; import java.util.List; /** * @A ...

  9. Java Map集合 遍历 五种方式(包含 Lambda 表达式遍历)

    示例代码如下: package com.miracle.luna.lambda; import java.util.HashMap; import java.util.Iterator; import ...

  10. Java中的集合概述

    Java中的集合类有两个重要的分支,分别是接口Collection(包括List,Set等)和接口Map. 由于HashSet的内部实现原理使用了HashMap,所以我们先来了解Map集合类. 1.H ...

随机推荐

  1. Java模拟Oracle函数MONTHS_BETWEEN注意事项

    Java模拟Oracle函数MONTHS_BETWEEN注意事项 MONTHS_BETWEEN(DATE1, DATE2) 用来计算两个日期的月份差. 最近接到一个迁移需求,把Oracle SQL接口 ...

  2. vue前端代码npm install报错的解决方法

    npm install,报错: npm WARN tarball tarball data for has-bigints@https://registry.npmmirror.com/has-big ...

  3. ES6 面试题

    新增了哪些属性? 新增块级作用域:let.const 新增数据类型:Symbol 表示独一无二的值 新增数据结构: Set,类似数组,所有数据是唯一的: Map,键值对的结合,传统的 Object 只 ...

  4. Linux 添加开机自启动

    rc.local 方式 一.& 在 Linux 命令后加上 &  可以在后台运行 二.nohup 对 SIGHUP 信号免疫,对 SIGINT 信号不免疫,可用 shopt | gre ...

  5. Linux系统 tcpdump 抓包命令使用教程

    tcpdump 是Linux系统下的一个强大的命令,可以将网络中传送的数据包完全截获下来提供分析.它支持针对网络层.协议.主机.网络或端口的过滤,并提供and.or.not等逻辑语句来帮助你去掉无用的 ...

  6. "有邻"创始人:APP覆盖杭州千余小区 却还没认真想过赚钱的事

    "远亲不如近邻",常被社区经济"掘金者"拿来做开场语. 在杭州,有不少互联网创业企业在深挖社区经济,例如社区O2O服务平台.杨仁斌也看中了"社区&qu ...

  7. The "https://packagist.phpcomposer.com/packages.json" file could not be down

    composer自身版本太低了,更新下 composer self-update 使用阿里云镜像 composer config -g repo.packagist composer https:// ...

  8. snpEff安装

    下载安装包: wget http://sourceforge.net/projects/snpeff/files/snpEff_v3_6_core.zip 解压安装包: unzip snpEff_v3 ...

  9. Solution Set - “愿所有罗盘都指向那片海洋”

    目录 0.「NOI Simu.」哈希计数 1.「NOI Simu.」运输计划 2.「NOI Simu.」时代的眼泪 3.「Subset」LP 的被动练习 4.「EC Final 2018」「LOJ # ...

  10. React源码解析(1): JSX语法与react项目渲染过程

    好家伙   0.前言 由于工作的需要,我不得不入手了react的全家桶,曾经我的主要技术栈是vue. 从vue转到react,一开始我感到非常不适应,jsx的语法的不了解,react hooks的使用 ...