JDK8-2-流(3)- 流操作-distinct

news2024/7/6 19:48:29

JDK8-2-流(3)- 流操作-distinct

去重操作,如下开头两个菜品一样,对 menu 去重如下:

public class DishDistinctTest1 {

    public static final List<Dish> menu = Arrays.asList(
            new Dish("pork", false, 800, Dish.Type.MEAT),
            new Dish("pork", false, 800, Dish.Type.MEAT),
            new Dish("beef", false, 700, Dish.Type.MEAT),
            new Dish("chicken", false, 400, Dish.Type.MEAT),
            new Dish("french fries", true, 530, Dish.Type.OTHER),
            new Dish("rice", true, 350, Dish.Type.OTHER),
            //季节水果
            new Dish("season fruit", true, 120, Dish.Type.OTHER),
            new Dish("pizza", true, 550, Dish.Type.OTHER),
            //虾
            new Dish("prawns", false, 300, Dish.Type.FISH),
            //鲑鱼,三文鱼,
            new Dish("salmon", false, 450, Dish.Type.FISH));


    public static void distinctTest() {
        List<Dish> dishList = menu.stream()
                .distinct()
                .collect(Collectors.toList());
        System.out.println(dishList);
    }

    public static void main(String[] args) {
        distinctTest();
    }
}

注意: 对象去重需要重写 equals 和 hashCode 方法(默认对象 equals 方法比较的是对象内存地址是否一致),由 distinct 内部具体实现类 java.util.stream.DistinctOps 可以看出这点。

java.util.HashSet

public boolean contains(Object o) {
    return map.containsKey(o);
}

java.util.HashMap

public boolean containsKey(Object key) {
    return getNode(hash(key), key) != null;
}

IDEA 如何自动生成 equals 和 hashCode 方法

空白处右键选择 Generate 或者Alt + Ins 快捷键

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Dish dish = (Dish) o;
    return vegetarian == dish.vegetarian && calories == dish.calories && Objects.equals(name, dish.name) && type == dish.type;
}

@Override
public int hashCode() {
    return Objects.hash(name, vegetarian, calories, type);
}

使用 filter 方法去重

假设现在需求有变,菜品 Dish 只要名称、是否素食、类型一致即可判断为重复,最直接的方法就是改动 Dish 类中 equals 和 hashCode 方法实现,但是这样会改变原有的规则,导致原来的代码有问题,而且假设还有其他去重的逻辑,那也无法同时满足。

如何实现

① 定义一个 String 类型 的 Set
② 将 Dish 中 name、vegetarian、type 属性拼接成字符串加入到 set 中,利用 Set 集合中无法添加重复元素的特性过滤掉没有成功添加的元素
代码如下:

public class DishDistinctTest2 {

    public static final List<Dish> REPEATED_DISHES = Arrays.asList(
            new Dish("pork", false, 790, Dish.Type.MEAT),
            new Dish("pork", false, 800, Dish.Type.MEAT),
            new Dish("beef", false, 700, Dish.Type.MEAT),
            new Dish("beef", false, 690, Dish.Type.MEAT)
    );

    private static <T> Predicate<T> distinctByKey(Function<? super T, String> keyExtractor) {
        Set<String> set = ConcurrentHashMap.newKeySet();
        return t -> set.add(keyExtractor.apply(t));
    }

    public static void distinctTest2() {
        List<Dish> dishList = REPEATED_DISHES.stream()
                .filter(
                        distinctByKey(
                                dish -> String.join("-",
                                        dish.getName(), Boolean.toString(dish.isVegetarian()), dish.getType().toString()
                                )
                        )
                )
                .collect(Collectors.toList());
        System.out.println(dishList);
    }

    public static void main(String[] args) {
        distinctTest2();
    }
}

打印结果:

[Dish{name='pork', vegetarian=false, calories=790, type=MEAT}, Dish{name='beef', vegetarian=false, calories=700, type=MEAT}]

其中重点代码为 distinctByKey 方法
如果难以理解的话,可以将以上代码用 JDK7 的方式写,如下:

public static void distinctTestWithJDK7() {
    List<Dish> dishList = new ArrayList<>();
    Set<String> set = ConcurrentHashMap.newKeySet();
    for (Dish dish : REPEATED_DISHES) {
        String key = String.join("-", dish.getName(), Boolean.toString(dish.isVegetarian()), dish.getType().toString());
        if (set.add(key)) {
            dishList.add(dish);
        }
    }
    System.out.println(dishList);
}

重复的元素如何保留想要的那一个

① new Dish(“pork”, false, 790, Dish.Type.MEAT),
② new Dish(“pork”, false, 800, Dish.Type.MEAT),
③ new Dish(“beef”, false, 700, Dish.Type.MEAT),
④ new Dish(“beef”, false, 690, Dish.Type.MEAT)

从上面例子的打印结果可以看出保留的是①、③号元素,即两个元素如果重复则保留顺序靠前的,假设现在需求要保留低卡路里的呢
很容易可以想到可以先按照卡路里排序再去重,代码如下:

public static void distinctTest3() {
    Comparator<Dish> comparator = Comparator.comparing(Dish::getName).reversed().thenComparing(Dish::getCalories);
    List<Dish> dishList = REPEATED_DISHES.stream()
            .sorted(comparator)
            .filter(distinctByKey(dish -> String.join("-", dish.getName(), Boolean.toString(dish.isVegetarian()), dish.getType().toString())))
            .collect(Collectors.toList());
    System.out.println(dishList);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/649037.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

享元模式(十四)

每天都是全新的一天&#xff0c;感谢今日努力的自己。 上一章简单介绍了外观模式(十三), 如果没有看过, 请观看上一章 一. 享元模式 引用 菜鸟教程里面的外观模式介绍: https://www.runoob.com/design-pattern/flyweight-pattern.html 享元模式&#xff08;Flyweight Patter…

后,配置文件被清空,导致无法开启WiFi

root cause&#xff1a; /data/vendor/wifi/wpa/wpa_supplicant.conf 是0字节&#xff0c;导致wpa_supplicant_init_iface缺少”p2p_disabled1“的配置就会在走错flow到p2p wpa_supplicant_init_iface 》wpas_p2p_init 从而在HidlManager::registerInterface 进入 if (isP2pIf…

DeepSpeed零冗余优化器Zero Redundancy Optimizer

零冗余优化器 内容 零概述培训环境启用零优化 训练 1.5B 参数 GPT-2 模型训练 10B 参数 GPT-2 模型使用 ZeRO-Infinity 训练万亿级模型 使用 ZeRO-Infinity 卸载到 CPU 和 NVMe分配 Massive Megatron-LM 模型以内存为中心的平铺注册外部参数提取权重 如果您还没有这样做&…

【LeetCode】HOT 100(12)

题单介绍&#xff1a; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合初识算法与数据结构的新手和想要在短时间内高效提升的人&#xff0c;熟练掌握这 100 道题&#xff0c;你就已经具备了在代码世界通行的基本能力。 目录 题单介绍&#…

佩戴比较舒适的蓝牙耳机有哪些?值得入手的蓝牙耳机分享

​对于年轻人来说&#xff0c;耳机使用场景丰富&#xff0c;时尚追求度高&#xff0c;喜好的音乐类型也是多种多样&#xff0c;需求侧重也不尽相同。下面我来推荐几款相当不错的蓝牙耳机给大家&#xff0c;总会有喜欢那款&#xff01; 一、南卡OE蓝牙耳机 佩戴舒适度打分&…

【QQ界面展示-设置消息正文的背景图 Objective-C语言】

一、咱们上午说到哪儿了,还记得吗, 1.咱们上午是不是说到这儿了,可以显示正文、可以显示文字、并且,设置好背景图片了, 现在的问题就是,正文里面的文字,是不是超出这个图片了, 正文里面的文字,超出背景图片了, 那么,接下来,就给大家看一下,怎么解决这个问题, …

Macbook Pro双系统装Window10后设置触摸屏滑动方向

最近想给自己的Macbook Pro装Windows10操作系统&#xff0c;毕竟Windows才是真正的生产力工具&#xff0c;装了以后不需要两台笔记本了&#xff0c;直接在一台笔记本上有MacOS和Windows 装好以后发现触摸屏不能轻点触控还有触摸屏的滑动方向是反的 第一个问题&#xff0c;不能轻…

Ansys Zemax | 如何在序列模式下模拟分光棱镜

概述 这篇文章介绍了&#xff1a; 如何在序列模式下使用多重结构创建分光棱镜 如何在布局图以及分析/计算窗口中同时追迹透射和反射光线 在考虑偏振及镀膜的影响下如何计算透射和反射光线的总能量 &#xff08;联系我们获取文章附件&#xff09; 介绍 在 OpticStudio 中…

xxlJob任务管理平台500:xxl-job remoting error(connect timed out)

目录 一、问题截图 二、问题处理 2.1.查看执行器地址 2.2.查看本地端口 2.3.总结 三、关于地址的题外话 一、问题截图 此时可以看到code500&#xff0c;msg是连接超时&#xff0c;说明地址不通&#xff0c;那就是查看地址配置。 二、问题处理 2.1.查看执行器地址 …

使用CloudOS帮助企业落地云原生PaaS平台

PaaS究竟是什么&#xff1f; IaaS、SaaS的定义很清楚&#xff0c;而PaaS的定义就比较宽泛。所以&#xff0c;很多人把PaaS当做一个万能的“框”&#xff0c;什么都往里装&#xff0c;特别像一排垃圾桶中的那个“其他垃圾”桶&#xff0c;当你拎了一袋垃圾&#xff0c;不知道往…

C++技能 ( 3 ) - 详解泛型模版和特化模版的使用【函数模版、类模版、模版全特化、模版局部特化、可变参数模版、模版模版参数】

系列文章目录 C技能系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 期待你的关注哦&#xff01;&#xff01;&#xff01;有更多博文系列等着看哦&#xff0c;会经常更新&#xff01;&#xff01;&#xff01; 因为你的关注激励着我的创作&#xff01…

网安云新品速递 | 移动应用安全检测服务,为App合规与安全保驾护航

移动应用安全攻击层出不穷 近年来&#xff0c;移动应用安全攻击事件频发&#xff0c;衍生出的用户数据安全问题&#xff0c;也逐渐成为用户、社会&#xff0c;乃至整个国家高度重视的问题。立法层面上&#xff0c;数据安全保护不断加强&#xff1b;监管层面上&#xff0c;相关…

当亲戚知道我是程序员后,对我一顿梭哈……

当亲戚知道我是程序员后&#xff1a; 有的让我修电脑&#xff1b; 有的让我PS&#xff1b; 有的让我扯网线&#xff1b; 有的让我搞路由器&#xff1b; 这次的亲戚&#xff0c;让我干起了老本行&#xff1a;软件开发。 他是做人力资源公司的&#xff0c;要让我开发个招聘…

Spark SQL数据源 - 基本操作

文章目录 一、案例演示读取Parquet文件二、在Spark Shell中演示课堂练习1、将4.1节的student.txt文件转换成student.parquet课堂练习2、读取student.parquet文件得到学生数据帧&#xff0c;并显示数据帧内容三、在IntelliJ IDEA里演示 一、案例演示读取Parquet文件 执行命令&a…

#提升开源项目质量与效率:使用 GitHub Actions 自动化流程

提升开源项目质量与效率&#xff1a;使用 GitHub Actions 自动化流程 简介&#xff1a; 在开源项目中&#xff0c;质量和效率是至关重要的因素。本文将介绍如何利用 GitHub Actions&#xff0c;结合 ChatGPT Code Review、Autofix、Codecov 和 Publish PyPI 四个强大的 Actio…

unbound配置cache服务器

unbound 安装unbound配置unbound生成DOT证书配置日志监听哪个IP允许哪些客户端查询配置转发DNSSEC开启domain-insecure生成密钥 检查配置查看缓存启动Unbound服务&#xff1a; 结果验证方法1&#xff1a;方法2: 排错方法 安装unbound 以下是将DNS over TLS&#xff08;DoT&…

一文吃透Spring集成MyBatis

个人主页&#xff1a; 几分醉意的CSDN博客_传送门 文章目录 &#x1f496;集成思路✨怎么使用MyBatis✨集成的步骤✨pom加入依赖✨创建MyBatis使用代码✨创建Service类✨创建Spring配置文件和测试集成MyBatis✨使用外部属性配置文件 &#x1f496;图书推荐 Java28岁了&#xff…

CRC校验(2):CRC32查表法详解、代码实现和CRC反转

对于现在的CPU来说&#xff0c;基本上都在硬件上实现了CRC校验。但我们还是想用软件来实现一下CRC的代码&#xff0c;这样可以更深入地理解里面的原理。所以这一节就来详细地解释如何使用查表法从软件上来实现CRC-32的校验。另外&#xff0c;CRC还有一种反转的情况&#xff0c;…

SpringCloud Ribbon负载均衡(十一)

前面搭建了初步例子&#xff0c;但是还没实现真正负载均衡&#xff0c;我们这里要先搞三个服务提供者集群&#xff0c;然后才能演示负载均衡&#xff0c;以及负载均衡策略&#xff1b; 新建项目microservice-student-provider-1002&#xff0c;microservice-student-provider-…

行星减速机优势有哪些?行星减速机五大优势

减速机是动力传动解决方案&#xff0c;通过选择高质量和高效率的变速箱&#xff0c;绝对可以提高整个动力传动系统的效率和性能。行星减速机有哪些优势呢&#xff1f; 1.保证灵活可靠的动力传动系统 减速机提供了广泛的功率和比率&#xff0c;使其成为许多行业的大多数应用的完…