Java8如何通过Stream对list对象某个属性去重

 更新时间:2026年07月06日 09:50:20   作者:楚辞大魔王  
学会Java8 Stream与TreeSet高效List去重!本文详解对象整体去重、单属性及多属性去重实战代码,直接复制即可用,点击立即掌握集合去重技巧,提升开发效率

前言

对于list集合进行去重操作,多种情况进行记录.

只记录在学习与实践过程中需要对集合操作的场景,方便下次能够直接快速的回忆起来.

当然这些方法的使用与操作皆是对于Java8stream操作,TreeSet不重复特性进行的运用.

如果能够更好更快的达成目的,也是不必拘泥于某一些固定的方式去处理数据,以效率与程序开销优先.

正文

数据对象

将数据对象写成静态不可变的list来方便我们对于程序进行调用验证

private static final List<SyncBalance> list = asList(
        new SyncBalance(BigDecimal.ZERO, "12345678", 0, 1, "GGBond", 32, 0),
        new SyncBalance(BigDecimal.ZERO, "22345678", 0, 1, "GGBond", 32, 0),
        new SyncBalance(BigDecimal.ZERO, "22345678", 1, 1, "GGBond", 32, 0),
        new SyncBalance(BigDecimal.ZERO, "22345678", 1, 1, "GGBond", 32, 0)
);

1. 对象整体去重

/**
 * 1. 对所有属性一样的数据进行去重
 */
public static void allColumnDistinct() {
    List<SyncBalance> allColumnDistinct = list.stream().distinct().collect(Collectors.toList());
}

2. 单个属性去重(只返回属性)

/**
 * 2. 对单个属性去重,只返回去重的属性
 */
public static void columnDistinct() {
    List<String> columnDistinct = list.stream().map(SyncBalance::getMobile).distinct().collect(Collectors.toList());
}

3. 单个属性去重

/**
 * 3-1. 对单个属性一样的数据进行去重,下面是对`mobile`去重
 */
public static void oneColumnDistinctMethodOne() {
    List<SyncBalance> oneColumnDistinctMethodOne = list.stream().collect(Collectors.collectingAndThen(
            Collectors.toCollection(() -> new TreeSet<>(
                    Comparator.comparing(SyncBalance::getMobile))), ArrayList::new));
}
/**
 * 3-2. 对单个属性一样的数据进行去重,下面是对`mobile`去重(通过自定义属性去重方法)
 */
public static void oneColumnDistinctMethodTwo() {
    List<SyncBalance> oneColumnDistinctMethodTwo = list.stream().filter(distinctByKey(i -> i.getMobile())).collect(Collectors.toList());
}

/**
* list对象单个个字段去重(自定义属性)
* @param keyExtractor 去重的对象字段
* @return
* @param <T>
*/
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Map<Object, Boolean> seen = new ConcurrentHashMap<>();
    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
/**
 * 3-3. 对单个属性一样的数据进行去重,下面是对`mobile`去重
 * 利用TreeSet进行去重
 */
public static void oneColumnDistinctMethodThree() {
    TreeSet<SyncBalance> oneColumnDistinctMethodThree = new TreeSet<>(Comparator.comparing(i -> i.getMobile()));
    list.forEach(a -> oneColumnDistinctMethodThree.add(a));
}

4. 多个属性去重

/**
 * 4. 多个字段条件去重
 */
public static void twoColumnDistinct() {
    List<SyncBalance> twoColumnDistinct = list.stream().collect(Collectors.collectingAndThen(
            Collectors.toCollection(() -> new TreeSet<>(
                    Comparator.comparing(p -> p.getMobile() + ";" + p.getStatus()))), ArrayList::new));
}

验证方法

对于验证方法添加了一些分隔的数据

/**
 * 验证的main方法
 * @param args
 */
public static void main(String[] args) {
    allColumnDistinct();
    columnDistinct();
    oneColumnDistinctMethodOne();
    oneColumnDistinctMethodTwo();
    oneColumnDistinctMethodThree();
    twoColumnDistinct();
}

运行结果

allColumnDistinct---v
SyncBalance(accountBalance=0, mobile=12345678, status=0, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
SyncBalance(accountBalance=0, mobile=22345678, status=0, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
SyncBalance(accountBalance=0, mobile=22345678, status=1, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
allColumnDistinct---^
columnDistinct---v
12345678
22345678
columnDistinct---^
oneColumnDistinctMethodOne---v
SyncBalance(accountBalance=0, mobile=12345678, status=0, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
SyncBalance(accountBalance=0, mobile=22345678, status=0, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
oneColumnDistinctMethodOne---^
oneColumnDistinctMethodTwo---v
SyncBalance(accountBalance=0, mobile=12345678, status=0, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
SyncBalance(accountBalance=0, mobile=22345678, status=0, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
oneColumnDistinctMethodTwo---^
oneColumnDistinctMethodThree---v
SyncBalance(accountBalance=0, mobile=12345678, status=0, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
SyncBalance(accountBalance=0, mobile=22345678, status=0, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
oneColumnDistinctMethodThree---^
twoColumnDistinct---v
SyncBalance(accountBalance=0, mobile=12345678, status=0, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
SyncBalance(accountBalance=0, mobile=22345678, status=0, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
SyncBalance(accountBalance=0, mobile=22345678, status=1, sysId=1, loginAccountName=GGBond, keepOrUpdate=32, id=0)
twoColumnDistinct---^​

结尾

集合的操作不止拘泥于stream流TreeSet可以处理,其他一下如果可以实现皆可使用.

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 详解DES加密算法及在Java程序中的使用示例

    详解DES加密算法及在Java程序中的使用示例

    这篇文章主要介绍了详解DES加密算法及在Java程序中的使用示例,文中还有一个用Java实现的DES三重加密的例子,需要的朋友可以参考下
    2016-04-04
  • Netty网络编程零基础入门

    Netty网络编程零基础入门

    Netty是一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端,如果你还不了解它的使用,就赶快继续往下看吧
    2022-08-08
  • 剑指Offer之Java算法习题精讲二叉搜索树与数组查找

    剑指Offer之Java算法习题精讲二叉搜索树与数组查找

    跟着思路走,之后从简单题入手,反复去看,做过之后可能会忘记,之后再做一次,记不住就反复做,反复寻求思路和规律,慢慢积累就会发现质的变化
    2022-03-03
  • java中接口幂等性的五种实现方法

    java中接口幂等性的五种实现方法

    在java中保证接口幂等性,即多次调用同一接口产生与单次调用相同的结果,不会引发副作用,需要结合业务场景选择合适的方案,下面就来介绍五种实现方法,感兴趣的可以了解一下
    2025-09-09
  • 关于MyBatis模糊查询的几种实现方式

    关于MyBatis模糊查询的几种实现方式

    在实际项目中,我们会经常对数据做一些模糊查询的操作,这时候就需要利用到 like字段,那么在Mybatis中,有哪些方式可以实现模糊查询呢,需要的朋友可以参考下
    2023-05-05
  • Springboot使用Websocket的时候调取IOC管理的Bean报空指针异常问题

    Springboot使用Websocket的时候调取IOC管理的Bean报空指针异常问题

    这篇文章主要介绍了Springboot使用Websocket的时候调取IOC管理的Bean报空指针异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • 详解Java并发编程之内置锁(synchronized)

    详解Java并发编程之内置锁(synchronized)

    这篇文章主要介绍了Java并发编程之内置锁(synchronized)的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • SpringBoot在自定义类中调用service层mapper层方式

    SpringBoot在自定义类中调用service层mapper层方式

    这篇文章主要介绍了SpringBoot在自定义类中调用service层mapper层方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • java使用数组和链表实现队列示例

    java使用数组和链表实现队列示例

    队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,只允许在表的后端(rear)进行插入操作,下面介绍一下java使用数组和链表实现队列的示例
    2014-01-01
  • JAVA使用前缀树(Tire树)实现敏感词过滤、词典搜索

    JAVA使用前缀树(Tire树)实现敏感词过滤、词典搜索

    本文主要介绍了JAVA使用前缀树(Tire树)实现敏感词过滤、词典搜索,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01

最新评论