咖啡汪日志——行为参数化及Collectors.toConcurrentMap源码浅析

2023-11-03

作为不是在逗比,就是在逗比路上的,拆家霸主
本汪今天就拆了Collectors.toConcurrentMap
看看他里面是怎么搞的
额,不了解函数式编程的小伙伴,推荐看下《java实战第二版》
看懂这篇博客,需要一定的函数式编程基础,起码得懂什么是行为参数化
不了解泛型的子类型规则,无限制的通配符类型的小伙伴,推荐以下博客
https://www.cnblogs.com/jian0110/p/10690483.html
在这里插入图片描述

一、开篇有益

行为参数化就是可以帮助你处理频繁变更的需求的一种软件开发模式。
本汪简单举个好理解的例子
1.我们定义一个对象,地球 -》作为一个参数对象; 执行 -》自转
2.我们定义一个对象,太阳 -》作为一个参数对象; 执行 -》发光发热
3.我们自定义一个对象,BloomFilter-》作为一个参数对象;执行 -》限流操作
4.我们定义另一个对象,MyLock -》 作为一个参数对象; 执行 -》锁升级,自旋 - 成功则升级/失败则重试
5.我们定义一个对象,字符串数组 -》 作为一个参数对象; 返回数组中非空的字符串

有没有一个方法,能被以上所有的案例使用呢?
JDK1.8以前做不到,JKD1.8以后可以了
想一下,我们可以写一个方法,把对象+行为作为参数传入,eg:

 public void used( 我是一个对象,什么类型的都可以Object object,
 我是一个行为,什么行为都行Active<T> active ) {
              那么这里:  1.地球 + 自旋
                        2.太阳 + 发光发热
                        3.BloomFilter + 限流
                        4.MyLock + 锁升级,自旋 - 成功则升级/失败则重试
                        5.字符串数组 + 返回数组中非空的字符串
        }

这就是所谓的行为参数化了
现在写个简单的例子,定义一个used方法,使得她可以对同一个字符串数组,进行不同的操作,带大家看一下,她具体的代码实现

一下代码中,我们把“对象 和 具体行为操作”作为参数,传入方法used(对象,行为)

1、我们先定义一个函数式接口,ReturnBoolean<T>, 她可以接受一个对象,返回一个boolean值,定义她的目的是为了对应Lambda表达式的解析
这儿本汪插一句,如果java.util.function下有相同功能的函数接口,大家就不要自己另定义了,这儿只是为了举例子(其实相当与Predicate <T )

@FunctionalInterface
public interface ReturnBoolean<T> {
    boolean active(T t);
}

此处相当与上面的used()方法,List -》对象 ,ReturnBoolean<T> 行为(执行的操作)


    public <T> List<T> filter(List<T> list ,ReturnBoolean<T> r) {
        List<T> results = new ArrayList<>();
        for (T t : list) {
            if (r.active(t)) {
                results.add(t);
            }
        }
        return results;

    }

使用时,传入他的具体行为:

ReturnBoolean<String> r = (String i) -> !i.isEmpty();// 字符串数组为对象 行为:筛选数组中的非空字符串
    ReturnBoolean<String> r1 = (String i) -> i.contains("a");//字符串数组为对象 行为:筛选数组中包含“a”的字符串
    ReturnBoolean<Integer> i1 = (Integer i) -> i > 0;//Integer数组中,行为:筛选大于0 的数据
    ReturnBoolean<Car> u1 = (Car car) -> car.canRun();//List<Car>,行为:筛选还能跑的汽车
    List<String> strings = Arrays.asList("ss","sdfka","","abc");
    List<String> str = used(strings,r);












二、Collectors.toConcurrentMap源码解析

这儿本汪多句嘴
ConcurrentHashMap在JDK1.8做了大的变动,底层结构变为了数组+链表+红黑树,
内部也由Entry节点,变为了Node节点,
与HashTable对所有方法加Synchornized锁不同,她只会锁相关的node节点,这点不清楚,后面可能看不懂,
由于根据泊松分布,当默认负载因子为0.75时,单个Hash曹内存在8个元素的概率小于百万分之一,所以当元素数>=8时,链表->红黑树;<=6时,红黑树->链表; 7的时候不变动
嗯,这下差不多了,进入正题

public ConcurrentHashMap<String,Long> getList() 
{
            return LongStream.rangeClosed(1,10)
                    .boxed()
                    .collect(Collectors.toConcurrentMap(i -> "a", identity(),
            (o1,o2) -> o1,ConcurrentHashMap::new));
        }
        

我们进入Collectors.java,找到她

 public static <T, K, U, M extends ConcurrentMap<K, U>>
    Collector<T, ?, M> toConcurrentMap
    (
    Function<? super T, ? extends K> keyMapper,
    Function<? super T, ? extends U> valueMapper,
    BinaryOperator<U> mergeFunction,
    Supplier<M> mapSupplier
   ) {
  BiConsumer<M, T> accumulator
  = (map, element) -> map.merge(keyMapper.apply(element),
	valueMapper.apply(element), mergeFunction);
  return new CollectorImpl<>(mapSupplier, accumulator,               mapMerger(mergeFunction), CH_CONCURRENT_ID);
    }
    

其实很简单:
Function<? super T, ? extends K> keyMapper进行key的映射
Function<? super T, ? extends U> valueMapper进行value的映射
BinaryOperator<U> mergeFunction是一个双重操作,(o1,o2)-> o1,

本汪不放心:所以还是说下吧,不然有的小伙伴真的在听天书
public int getNewObject(int o1,int o2){
return o1 > o2 ? o1 : o2;
}
->
传入两个相同类型的参数,返回一个返回值(也是相同的类型)
Supplier<M> mapSupplier提供实现ConcurrentMap的具体实现类
进入map.merge(keyMapper.apply(element), valueMapper.apply(element), mergeFunction)继续查看

 @Override
    default V merge(K key, V value,
            BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        Objects.requireNonNull(value);
        V oldValue = get(key);//通过传入的key获取旧的value值
        for (;;) {
        //如果可以从原Map中拿到value,把她看做是一个旧的value,
            if (oldValue != null) {
            //有旧的value时,把她和我们新传进来的value,作比较
            //如果不相等,返回新的value
           V newValue = remappingFunction.apply(oldValue, value);
                //如果返回了新的value,就调用ConcurrentHashMap中的replace方法进行置换,看到没,置换的是node节点哦!
                /*
        public boolean replace(K key, V oldValue, V newValue) {
        if (key == null || oldValue == null || newValue == null)
            throw new NullPointerException();
        return replaceNode(key, newValue, oldValue) != null;
    }
    */
              
                if (newValue != null) {
                    if (replace(key, oldValue, newValue))
                        return newValue;
                        //如果无新值,或新值为null,返回null
                } else if (remove(key, oldValue)) {
                    return null;
                }
                oldValue = get(key);
            } else {
                if ((oldValue = putIfAbsent(key, value)) == null) {
                    return value;
                }
            }
        }
    }
    

今天到这儿,先稍微了解一下她的实现,后面有时间,我们继续拆。。。。。。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

咖啡汪日志——行为参数化及Collectors.toConcurrentMap源码浅析 的相关文章

  • Java中反射是如何实现的?

    Java 7 语言规范很早就指出 本规范没有详细描述反射 我只是想知道 反射在Java中是如何实现的 我不是问它是如何使用的 我知道可能没有我正在寻找的具体答案 但任何信息将不胜感激 我在 Stackoverflow 上发现了这个 关于 C
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • 无法解析插件 Java Spring

    我正在使用 IntelliJ IDEA 并且我尝试通过 maven 安装依赖项 但它给了我这些错误 Cannot resolve plugin org apache maven plugins maven clean plugin 3 0
  • 如何为俚语和表情符号构建正则表达式 (regex)

    我需要构建一个正则表达式来匹配俚语 即 lol lmao imo 等 和表情符号 即 P 等 我按照以下示例进行操作http www coderanch com t 497238 java java Regular Expression D
  • Java TestNG 与跨多个测试的数据驱动测试

    我正在电子商务平台中测试一系列商店 每个商店都有一系列属性 我正在考虑对其进行自动化测试 是否有可能有一个数据提供者在整个测试套件中提供数据 而不仅仅是 TestNG 中的测试 我尝试不使用 testNG xml 文件作为机制 因为这些属性
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • Java Integer CompareTo() - 为什么使用比较与减法?

    我发现java lang Integer实施compareTo方法如下 public int compareTo Integer anotherInteger int thisVal this value int anotherVal an
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will
  • JGit 检查分支是否已签出

    我正在使用 JGit 开发一个项目 我设法删除了一个分支 但我还想检查该分支是否已签出 我发现了一个变量CheckoutCommand但它是私有的 private boolean isCheckoutIndex return startCo
  • java.lang.IllegalStateException:驱动程序可执行文件的路径必须由 webdriver.chrome.driver 系统属性设置 - Similiar 不回答

    尝试学习 Selenium 我打开了类似的问题 但似乎没有任何帮助 我的代码 package seleniumPractice import org openqa selenium WebDriver import org openqa s
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j

随机推荐

  • [C#] 计算字符串在控制台上显示的宽度, 包含所有Char能表示的字符!

    通过运算 获取字符串在控制台上现实的宽度 单位为一个英文字母的宽度 高度为控制台中一行的高度 在网上找了半天 唯一一个正儿八经的 就是通过GBK编码的字节数来推测所占宽度 但我认为这个有点不大妥当 例如某些特殊字符 可能就不被GBK编码包含
  • 锚点定位内容被遮挡,css解决方案

    问题 头部header使用position fixed 下方内容用锚点定位跳转 内容部分被header遮挡 解决 1 在跳转的内容上方加个空div 2 锚点id加到空div上 空div写css并设置样式
  • java 20个IDEA最常用的快捷键 介绍及演示

    目录 一 前言 二 20个常用快捷键的演示 1 撤销和反撤销 Ctrl z 和 Ctrl y 注意Ctrl y 2 复制当前行 可多选 Ctrl d 3 删除当前行 可多选 Ctrl e 非默认 4 移动当前行 可多选 Alt Shift
  • 数据结构视频教程 -《零基础学算法》

    打包下载请访问 史上最全的数据结构视频教程系列分享之 零基础学算法 转载请保留出处和链接 更多优秀资源请访问 我是码农 本教程主要分为上 下两部分 共10章 上篇用5章的篇幅介绍了算法和数据结构的基础知识 包括基础算法思想 简单数据结构 复
  • [QT编程系列-5]:C++图形用户界面编程,QT框架快速入门培训 - 2- QT程序的运行框架:事件(用于与系统的交互)、信号(对象与对象之间的通信)

    目录 2 QT程序的运行框架 2 5 事件的捕获与处理 2 5 1 QT 事件与信号的区别 2 5 2 QT程序架构 2 5 3 QT的事件机制 2 QT程序的运行框架 2 5 事件的捕获与处理 2 5 1 QT 事件与信号的区别 在Qt中
  • 《原力计划文章》专栏目录

    前往老猿Python博客 https blog csdn net LaoYuanPython 一 专栏简介 原力计划文章 专栏收集的是老猿2021年参与CSDN原力计划的所有文章 二 文章目录 用Python通过摄像头进行视频录制 Pyth
  • 中国天气网全城市代码weather_cityId

    Ctrl F 查询 城市名字 http mobile weather com cn data forecast 101010100 html 1381891660081 北京 gt 101010100 海淀 gt 101010200 朝阳
  • TensorFlow 1.x学习(系列二 :4):自实现线性回归

    目录 线性回归基本介绍 常用的op 自实现线性回归预测 tensorflow 变量作用域 模型的保存和加载 自定义命令行参数 线性回归基本介绍 线性回归 w 1 x 1
  • VxWorks任务挂死实战分析

    目录 背景描述 根本原因 分析过程 背景描述 操作系统 VxWorks 5 5 CPU MIPS32 74Kc内核CPU 现象描述 联调代码时发现应用层代码调用以下接口函数必现任务挂死 检查代码发现入参均合法 代码逻辑没问题 未发现异常 F
  • HTTP与UDP的区别比较

    TCP Transmission Control Protocol 传输控制协议 与UDP User Data Protocol 用户数据协议 是互联网传输数据较为常用的协议 我们熟知的HTTP就是基于TCP的 二者区别 1 连接类型 TC
  • Java面向对象进阶&接口&多态&内部类

    1 接口 1 1学生信息管理系统集合改进 使用数组容器的弊端 容器长度是固定的 不能根据添加功能自动增长 没有提供用于赠删改查的方法 优化步骤 创建新的StudentDao类 OtherStudentDao 创建ArrayList集合容器对
  • 使用matlab训练卷积神经网络

    主流的深度学习都是使用Python操作的 由于Python接触较少 对其编码不熟悉 目前先是使用matlab进行搭建卷积神经网络 任务 二分类 网络 搭建的3层卷积神经网络 卷积 池化 激活 3 全连接层 样本 正负样本分别为5000张灰度
  • notifier chain — 内核通知链

    大多数内核子系统都是相互独立的 因此某个子系统可能对其它子系统产生的事件感兴趣 为了满足这个需求 也即是让某个子系统在发生某个事件时通知其它的子系统 Linux内核提供了通知链的机制 通知链表只能够在内核的子系统之间使用 而不能够在内核与用
  • 字符串操作相关函数

    1 C 库函数 int atoi const char str 把参数 str 所指向的字符串转换为一个整数 类型为 int 型 2 C 库函数 char strrchr const char str int c 在参数 str 所指向的字
  • mybatis plus 获取插入后自增id

    解决办法就是关掉mybatis自增长 在实体映射类里更改相关注解即可 用户ID TableId value user id type IdType AUTO 设置id自增 才能在插入后返回id 设置type才能显示正常的自增id 不设置ty
  • Linux下的sudo及其配置文件/etc/sudoers的详细配置说明

    Linux下的sudo及其配置文件 etc sudoers的详细配置说明 1 sudo介绍 sudo是linux下常用的允许普通用户使用超级用户权限的工具 允许系统管理员让普通用户执行一些或者全部的root命令 如halt reboot s
  • 【工具】2019 Adobe全家桶pdf——百度网盘下载(PS、AE、PR等)

    百度网盘地址 https pan baidu com s 14X4fm7cvBA17YOo110j6ng 资源来之不易 需要获取密码 请关注公众号 全栈船长 并回复数字 0012
  • Maven配置私有库

    Maven配置私有库 一 仓库 二 pom xml 三 settings xml文件 一 仓库 仓库类型 本地仓库 远程中央仓库 公司自己搭建的私有仓库 寻找jar的基本优先级顺序 本地仓库 gt settings xml的profile的
  • Mybatis学习笔记1 Mybatis入门

    差不多根据mybatis中文文档 创建第一个mybatismaven项目 将它跑起来 入门 MyBatis中文网 新建库 建表 创建项目 重启之后 配置下Maven与encoding 成习惯了 新建模块 注意 这个GroupId和Artif
  • 咖啡汪日志——行为参数化及Collectors.toConcurrentMap源码浅析

    作为不是在逗比 就是在逗比路上的 拆家霸主 本汪今天就拆了Collectors toConcurrentMap 看看他里面是怎么搞的 额 不了解函数式编程的小伙伴 推荐看下 java实战第二版 看懂这篇博客 需要一定的函数式编程基础 起码得