首页
友情链接
精美壁纸
给我留言
更多
关于我
Search
1
uniapp Click点击事件冲突解决
4,558 阅读
2
【插件】UNI APP 实现商米打印机功能支持T1,T2,V2机型
3,875 阅读
3
【测试可用】个人码免签支付系统源码/免签支付系统/微信支付平台
1,978 阅读
4
Java Validation参数校验注解使用
1,230 阅读
5
windows10下docker:给已存在的容器添加端口映射的方法
1,220 阅读
Java
Spring Boot
Spring Mvc
Java基础
进阶知识
前端
uniapp
小程序/公众号
JavaScript
HTML/CSS
Vue
PHP
开源软件
商城
营销工具
开发工具
视频/教程
Discuz主题/插件
typecho主题/插件
SEO杂谈
数据库
MongoDB
MySQL
Redis
单片机
概念说明
电路相关
Python
devops
docker
k8s
linux
职场杂谈
登录
/
注册
Search
标签搜索
python
mysql
人人商城
php
java
docker
typecho
插件
微擎
seo
spring boot
discuz
队列
uni-app
phpcms
教程视频
开源系统
源码
工具
css
哈根达斯
累计撰写
100
篇文章
累计收到
154
条评论
首页
栏目
Java
Spring Boot
Spring Mvc
Java基础
进阶知识
前端
uniapp
小程序/公众号
JavaScript
HTML/CSS
Vue
PHP
开源软件
商城
营销工具
开发工具
视频/教程
Discuz主题/插件
typecho主题/插件
SEO杂谈
数据库
MongoDB
MySQL
Redis
单片机
概念说明
电路相关
Python
devops
docker
k8s
linux
职场杂谈
页面
友情链接
精美壁纸
给我留言
关于我
搜索到
15
篇与
Java
的结果
2021-09-01
Java Stream 流式编程
前言在很多语言中都会有 map、reduce、filter 等高阶函数对应的流式编程。那么对应 Java 中的功能就是 Stream 操作。// 生成 1357 并打印Arrays.stream(new int[] {1, 3, 5, 7}).forEach(System.out::println);复制代码所以今天就整理一下关于 Java Stream 流式编程。关于 StreamStream 是 Java8 添加的一个新的抽象称为流,可以让你以一种声明的方式处理数据。Stream 可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。Stream 流的操作是以管道的方式串起来的。管道以数据源开始,包含若干个中间操作,最终以终点操作结束。简单使用下面介绍一下在 Java 中简单的使用:Map Filter ReduceList<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9); // 求和 // Integer sumResult = list.stream().reduce(0, (a, b) -> a + b); Integer sumResult = list.stream().reduce(0, Integer::sum); // 45 System.out.println(sumResult); // 遍历数组 list.forEach(System.out::print); // 123456789 System.out.println(); // 返回数组元素的平方 List<Integer> numbersList = list.stream().map(i -> i * i).collect(Collectors.toList()); // [1, 4, 9, 16, 25, 36, 49, 64, 81] System.out.println(numbersList); List<Integer> evenNumbersList = list.stream().filter(i -> i % 2 == 0).collect(Collectors.toList()); // 筛选出数组中的偶数 [2, 4, 6, 8] System.out.println(evenNumbersList); // 筛选出数组中的奇数并返回元素的平方 List<Integer> numbers = list.stream().filter(i -> i % 2 != 0).map(i -> i * i).collect(Collectors.toList()); System.out.println(numbers);Collector一般用于 stream 操作的结束,用于对结果集做返回值的定义或高级操作。常见操作用于返回特定的集合:Collectors.toList() Collectors.toMap() Collectors.toSet() Collectors.toCollection() Collectors.toConcurrentMap()下面列举常见 demo :List<String> language = List.of("Java", "Python", "Rust", "Go", "C++", "C", "C#", "JavaScript"); // 将数组中元素转化成大写字母并用逗号拼接 String collect1 = language.stream().collect(Collectors.collectingAndThen(Collectors.joining(","), String::toUpperCase)); // JAVA,PYTHON,RUST,GO,C++,C,C#,JAVASCRIPT System.out.println(collect1); // 实现按数组元素进行分组 Map<Integer, List<String>> collect2 = language.stream().collect(Collectors.groupingBy(String::length)); // {1=[C], 2=[Go, C#], 3=[C++], 4=[Java, Rust], 6=[Python], 10=[JavaScript]} System.out.println(collect2); // 转换成字符串长度与字符串的 hash map 有冲突后者覆盖前者 Set<String> collect3 = language.stream().collect(Collectors.toCollection(HashSet::new)); // language.stream().collect(Collectors.toSet()); // [C#, Java, C++, Rust, C, JavaScript, Go, Python] System.out.println(collect3); // 转换成字符串长度与字符串的 hash map 有冲突后者覆盖前者 Map<Integer, String> collect4 = language.stream().collect(Collectors.toMap(String::length, String::new,(existing, replacement) -> existing)); // {1=C, 2=Go, 3=C++, 4=Java, 6=Python, 10=JavaScript} System.out.println(collect4);进阶使用在简单使用中都是比较常见且统一理解的例子。下面看一下一些比较复杂的例子。数据准备Person 类用到了 Lombok 的 Builder、Data 注解。@Builder(toBuilder = true) @Data class Person { private Integer height; private Integer age; private String name; private String city; } Person p1 = new Person.PersonBuilder().name("bob").height(150).city("shanghai").age(15).build(); Person p2 = new Person.PersonBuilder().name("andy").height(160).city("beijing").age(18).build(); Person p3 = new Person.PersonBuilder().name("tom").height(170).city("xian").age(19).build(); Person p4 = new Person.PersonBuilder().name("cat").height(180).city("shanghai").age(25).build(); ArrayList<Person> persons = new ArrayList<>(); persons.add(p1); persons.add(p2); persons.add(p3); persons.add(p4);实例讲解如下代码实现的功能为:将人员数组按照年龄设置额外字段将数组中人员按照城市分组组内结果如有多人取身高最高的一员// 需要关于身高的 Comparator Comparator<Person> byHeight = Comparator.comparing(Person::getHeight); Map<String, Person> collect = persons.stream().peek(item -> { String temp = item.getAge() >= 18 ? "成年" : "未成年"; item.setExtra(temp); }).collect( Collectors.groupingBy( Person::getCity, Collectors.reducing(p1, BinaryOperator.maxBy(byHeight)) ) ); // {xian=Person(height=170, age=19, name=tom, city=xian, extra=成年), shanghai=Person(height=180, age=25, name=cat, city=shanghai, extra=成年), beijing=Person(height=160, age=18, name=andy, city=beijing, extra=成年)} System.out.println(collect);
2021年09月01日
97 阅读
0 评论
0 点赞
2021-08-31
Java中ThreadLocal简单学习使用
文章目录索引ThreadLocal定义该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。以上来源官方API。大概可以总结为两点:ThreadLocal提供get/set方法,可以访问属于当前线程的变量,也就是可以保证每个线程的变量不一样。ThreadLocal使用时通常定义为private static的。从字面意思理解,可能会将ThreadLocal认为是本地线程,其实ThreadLocal并不是线程,而是线程Thread的局部变量。1、如何使用首先,定义一个private static的ThreadLocal对象。private static ThreadLocal<String> threadLocal = new ThreadLocal<>();然后每个线程可以将当前线程需要存放在局部变量中,并且可以从中获取。public void setAndGet(String name) { threadLocal.set(name); String s = threadLocal.get(); }最后在使用完之后,需要将ThreadLocal中的值移除。public void remove() { threadLocal.remove(); }2.原理那么ThreadLocal是如何做到保证每个线程get出来的数据不一样的呢?我们通过源码来看一下。public void set(T value) { Thread t = Thread.currentThread(); // 通过当前线程获取出来一个ThreadLocalMap ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }我们发现在set方法中,会创建一个ThreadLocalMap,然后将要设置的值放在这个Map中,而当前这个ThreadLocal对象作为key;然后再将这个ThreadLocalMap赋值给Thread的threadLocals里。如果去看Thread类的代码会发现,在Thread类中存在两个变量threadLocals和inheritableThreadLocals,它们的类型就是ThreadLocal.ThreadLocalMap。通过下图可以看出Thread,ThreadLocal,ThreadLocalMap三者的关系。这时候我们再看看get()和remove()方法的代码。public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; } public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); }可以看出来,和我们上面图中的结构一样,get()方法就是从Thread中取出来ThreadLocalMap,然后通过ThreadLocal对象作为Key取出值;remove()方法则是取出ThreadLocalMap将ThreadLocal对应的数据移除。那么ThreadLocalMap到底是什么呢?是java.util.Map接口的子类吗?我们来看源码。static class ThreadLocalMap { static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } private static final int INITIAL_CAPACITY = 16; private Entry[] table; private int size = 0; private int threshold; // Default to 0 // 省略其他代码 }通过源码发现,ThreadLocalMap并没有实现Map接口,也没有集成其他任何的Map类。是定义在ThreadLocal类中的一个静态内部类。而它的结构和HashMap结构极其相似。有一个Entry[]数组存放数据。而这个Entry类是继承自WeakReference类的子类,这一点和HashMap有所不同。ThreadLocalMap和HashMap结构有很多不同,但是还有一点和HashMap不一样,我们来看一下ThreadLocalMap的set方法。private void set(ThreadLocal<?> key, Object value) { Entry[] tab = table; int len = tab.length; // 计算key对应放在tab中的下标 int i = key.threadLocalHashCode & (len-1); //循环遍历tab,首先获取到下标i对应的对象,如果不为空,则执行循环体 // 如果不是相同的threadLocal或者位置失效,则要寻找下一个位置。 for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal<?> k = e.get(); // 判断与当前ThreadLocal是否是同一个对象,如果是则进行值替换,结束 if (k == key) { e.value = value; return; } // 如果k==null代表threadLocal的key失效了,将失效的key进行替换 if (k == null) { replaceStaleEntry(key, value, i); return; } } tab[i] = new Entry(key, value); int sz = ++size; if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); }代码中循环遍历tab,首先获取到下标i对应的对象,如果不为空,则执行循环体,如果在循环体中的两个条件都不满足,则会执行nextIndex()方法,这个方法的代码如下:private static int nextIndex(int i, int len) { return ((i + 1 < len) ? i + 1 : 0); }这个方法的逻辑就是 开放寻址法 。而HashMap则是通过 拉链法 和 rehash 来做的。3.使用场景通过上面的内容基本可以掌握ThreadLocal的基本用法,那么ThreadLocal主要在什么场景中使用呢。ThreadLocal的作用通过以上了解我们知道主要是用来做线程间数据隔离。那么在什么场景下能用到线程隔离呢?首先想到的就是SimpleDateFormat这个工具类,它不是线程安全的,可以通过ThreadLocal在每个线程中放一份,保证线程安全。还有比如说用户登录的session,或者token数据,只数据当前会话线程,也可以通过ThreadLocal存储。再比如在某些场景下,上下文数据在不同方法之间调用,传递起来非常麻烦,可以通过ThreadLocal存放,只需要在需要用到的地方获取就可以。除了这些场景,在某些框架源码中也会使用到,比如Spring中的事务也主要是通过ThreadLocal和面向切面编程AOP实现的,感兴趣的同学可以查看源码了解。4.避免踩坑内存泄漏ThreadLocalMap中的Entry的Key是一个弱引用,因此如果在使用后不调用remove方法清除掉会导致对应的value内存泄漏。所以在使用完以后一定要记得调用remove方法清除数据。
2021年08月31日
136 阅读
0 评论
0 点赞
2021-08-11
java中xml转移说明
被<![CDATA[]]>这个标记所包含的内容将表示为纯文本,比如<![CDATA[<]]>表示文本内容“<”。 此标记用于xml文档中,我们先来看看使用转义符的情况。我们知道,在xml中,”<”、”>”、”&”等字符是不能直接存入的,否则xml语法检查时会报错,如果想在xml中使用这些符号,必须将其转义为实体,如”<”、”>”、”&”,这样才能保存进xml文档。 在使用程序读取的时候,解析器会自动将这些实体转换回”<”、”>”、”&”。举个例子: <age> age < 30 </age> 上面这种写法会报错,应该这样写: <age> age < 30 </age> 值得注意的是: (1)转义序列字符之间不能有空格; (2) 转义序列必须以”;”结束; (3) 单独出现的”&”不会被认为是转义的开始; (4) 区分大小写。 在XML中,需要转义的字符有: (1) & & (2) < < (3) > > (4) " " (5) ' ' 但是严格来说,在XML中只有”<”和”&”是非法的,其它三个都是可以合法存在的,但是,把它们都进行转义是一个好的习惯。 不管怎么样,转义前的字符也好,转义后的字符也好,都会被xml解析器解析,为了方便起见,使用<![CDATA[]]>来包含不被xml解析器解析的内容。但要注意的是: (1) 此部分不能再包含”]]>”; (2) 不允许嵌套使用; (3)”]]>”这部分不能包含空格或者换行。 最后,说说<![CDATA[]]>和xml转移字符的关系,它们两个看起来是不是感觉功能重复了? 是的,它们的功能就是一样的,只是应用场景和需求有些不同: (1)<![CDATA[]]>不能适用所有情况,转义字符可以; (2) 对于短字符串<![CDATA[]]>写起来啰嗦,对于长字符串转义字符写起来可读性差; (3) <![CDATA[]]>表示xml解析器忽略解析,所以更快。
2021年08月11日
333 阅读
0 评论
0 点赞
2021-08-11
Java 书单:比较全的一篇
健康《程序员健康指南》- 链接:https://pan.baidu.com/s/1hb8xQCE3TrEjazF5ZCe6-w ,提取码:h6fh本书是为程序员量身制作的健康指南,针对头痛、眼部疲劳、背部疼痛和手腕疼痛等常见的问题,简要介绍了其成因、测试方法,并列出了每天的行动计划,从运动、饮食等方面给出详细指导,帮助程序员在不改变工作方式的情况下轻松拥有健康。之所以把这个放到第一位,是因为许多健康问题都是知道的越早越好,这样才能更好地预防Java 基础《Head First Java(第二版)》- 链接:https://pan.baidu.com/s/17LNLb-1s_k9wR1kK__s1eQ ,提取码:v3ae《Java核心技术卷一(第十版)》- 链接:https://pan.baidu.com/s/1l-pDMOkR832ceA5q2CVZ7g ,提取码:v88g《Java编程思想(第四版)》 - 链接:https://pan.baidu.com/s/1NwOrkSadZuL64DH43_5rKA ,提取码:jgorJava 进阶偏实战,需要打好上面的基础《Java8实战》- 链接:https://pan.baidu.com/s/1P6RBXi5PzRm4zuKgUr14sg ,提取码:q3lo《Java 并发编程实战》- 链接:https://pan.baidu.com/s/1m6ts-HSu2SgFVRgJKKPl6Q ,提取码:i7nz《实战Java高并发程序设计(第2版) 》- 链接:https://pan.baidu.com/s/1tSPNtR1CNGea6gKfXnBklA ,提取码:dad3《Java性能权威指南》- 链接:https://pan.baidu.com/s/1OlHlJ4qyPHQe5QMB6qkLmw ,提取码:vwca《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》- 链接:https://pan.baidu.com/s/1ZQi72jiqQzHlFhdkMqJtXg ,提取码:h7n7Java 优化下面主要讲解了Java开发常见的一些规范,使代码更加整洁高效《码出高效:Java开发手册》- 链接:https://pan.baidu.com/s/19sttAcC01G0wg1nqkfmprA ,提取码:zemp《Effective Java(第三版)》- 链接:https://pan.baidu.com/s/1RDaiVNViHvTVVunMkpFecg ,提取码:m9qe《嵩山版 Java 开发手册》- 链接:https://pan.baidu.com/s/1Rgh5tA_yPE-nV9MjPE572w ,提取码:62iw《代码整洁之道》《程序员修炼之道 从小工到专家》- 链接:https://pan.baidu.com/s/1lVoRCEr9NJR2I5rPneXK0g ,提取码:fxwe计算机《TCP-IP详解(卷一、二、三)》- 链接:https://pan.baidu.com/s/1D7luuYvEfTjaC7bh8Tm1Hg ,提取码:pmcj《深入理解计算机系统(原书第3版)》- 链接:https://pan.baidu.com/s/15F6MOyryXUI_l7DLoNbgiA ,提取码:7x0u算法《算法图解》- 链接:https://pan.baidu.com/s/1qbJAJbLInXo-rlPBGLOFUA ,提取码:k9nj《算法珠玑(Java版)》- 链接:https://pan.baidu.com/s/1EQj2sQk1Ys-EU8mwHho_MA ,提取码:7fxt《Leetcode 前 300 题算法题解析(Java)》- 链接:https://pan.baidu.com/s/1BGuMZW2ec4P_cyiv6sicww ,提取码:2jty设计模式《Head First 设计模式》- 链接:https://pan.baidu.com/s/1rxH5Ll38VpHl_j6ts6Q-oQ ,提取码:z6xg《Design-Pattern包教不包会(设计模式包教不包会)》- 链接:https://pan.baidu.com/s/1SDIsamZCv7JKY1zTuNLKtg ,提取码:81ci《设计模式 Java版本》- 链接:https://pan.baidu.com/s/1ikneBCgvAoIk5A-M6snIPg ,提取码:7b98《设计模式:可复用面向对象软件的基础》- 链接:https://pan.baidu.com/s/1CPJUAJp_oryQnKxWCbn8tA ,提取码:7qtiSpring 全家桶《Spring实战(第4版)》- 链接:https://pan.baidu.com/s/1CC1mAD4kZ57SmQRA8NEDXg ,提取码:ei6v《Spring Boot实战 》- 链接:https://pan.baidu.com/s/1QPfW43uN1uTJnsdKzUBDog ,提取码:aukv《Spring Boot 2企业应用实战》- 链接:https://pan.baidu.com/s/1s31xMCJ3WIjN2Koc-hSlyg ,提取码:3apd《JavaEE开发的颠覆者 Spring Boot实战》- 链接:https://pan.baidu.com/s/1TOmImwqszUDYmXc9uALaWg ,提取码:blpp《SpringBoot实战系列》- 链接:https://pan.baidu.com/s/1PPvY5goAI8L3SChfYSaAiw ,提取码:j26wMaven 依赖管理《Maven实战 高清》- 链接:https://pan.baidu.com/s/1MUZOKKjv5F7XY32aUIDaog ,提取码:xj6wMySQL 数据库《MySQL技术内幕(第5版)》- 链接:https://pan.baidu.com/s/1Dv6HXvhmyiGA2Gsn7NBo3w ,提取码:d7pj《MySQL技术内幕:InnoDB存储引擎(第2版)》- 链接:https://pan.baidu.com/s/1-dRbRaERiEJGIg3tgg00_A ,提取码:t4rh《高性能MySQL(第3版)》- 链接:https://pan.baidu.com/s/1yjHTlNcJLTaXjUAv2al0HA ,提取码:v037《Effective MySQL之SQL语句最优化》- 链接:https://pan.baidu.com/s/1IVWZw_JfL8y0KQ290gHT6w ,提取码:cbiy《SQL反模式》- 链接:https://pan.baidu.com/s/1C_jnScaSBw72ET_Qkh5phQ ,提取码:qspw《深入MySQL实战》- 链接:https://pan.baidu.com/s/14IP44JpJruedpOilLTiUog ,提取码:ejia《mybatis-plus 实践及架构原理》- 链接:https://pan.baidu.com/s/1bBVCVy6_YRM0aMeNOAveww ,提取码:joexRedis 数据库《redis设计与实现(第二版)》- 链接:https://pan.baidu.com/s/19mtOtYKLFWoY9fpP4v7MsA ,提取码:7cmx《Redis深度历险:核心原理和应用实践》- 链接:https://pan.baidu.com/s/1tVTucPsmwY2M5HJSNvhpCg ,提取码:oyiyRabbitMQ 消息队列《RabbitMQ实战 高效部署分布式消息队列》- 链接:https://pan.baidu.com/s/11btAl5txQLPd6DcT3hX0FA ,提取码:lmz5《深入RabbitMQ》- 链接:https://pan.baidu.com/s/1F4iCPSJGhBBQzaebC_E_BA ,提取码:nhp0架构《架构探险:从零开始写分布式服务框架》- 链接:https://pan.baidu.com/s/1_Eo4pqAekHVyBlJ7EIayZA ,提取码:lc2t《大型网站技术架构 核心原理与案例分析》- 链接:https://pan.baidu.com/s/1zt4Ee4sUnO4H654ZeuRxTg ,提取码:w1rb
2021年08月11日
112 阅读
0 评论
0 点赞
2021-08-05
MybatisPlus LambdaQueryWrapper类方法说明
方法含义对照表
2021年08月05日
243 阅读
0 评论
0 点赞
1
2
3