本文最后更新于:1 个月前
破冰 🍖 IntelliJ IDEA:一个不可或缺的利器
提升开发效率的利器:IntelliJ IDEA 在 Java 开发领域的重要性
探索功能和特性:深入探索 IntelliJ IDEA 的强大功能和特性
打造流畅编码之旅:分享实用技巧和优化工作流程的方法
从新手到高手的成长之路:为读者提供宝贵经验和指导
从基础到高级:从配置和设置开始,逐步介绍常用功能和高级技巧
启程进入 IntelliJ IDEA 世界:探索其中的奇妙与无穷可能
适用于初学者和经验丰富的开发者:为你打开高效编码的大门
享受 Java 开发的旅程:让我们一同探索这个编程基石的奥妙
推荐阅读 【尚硅谷】IDEA2022 快速上手开发利器_java2022idea 怎么使用-CSDN 博客
两年前自定义过的 Java 代码模板:
思维碰撞 激活
2025 年 2 月 27 日
IDEA/PyCharm/DataGrip/Goland..等JetBrains激活方法汇总 - 飞书云文档 (feishu.cn)
JetBrains全家桶激活 - 飞书云文档 (feishu.cn)
挺好用的教程,近两年来都是靠这个续命的,以防不久的将来可能会访问失败,现在把文中核心内容记录下来。
JetBrains全家桶激活
请尊重彼此的时间,认真看文档,不要再问文档中已经解决的问题
文末【常见问题】中,总结了大家经常遇到的几个问题, 认真看文档!
本破解教程除了适用于IDEA,同样适用于JetBrains全家桶,比如PyCharm、DataGrip、Goland、WebStorm等等
本次工具支持2021.3以后版本( 2021.3.1,2021.3.2,2021.3.3,2022.1,2022.1.1,2022.1.2,2022.1.3,2022.1.4,2022.2,2023.1,2023.2等等)的IDE使用
如果您是旧版本IDEA(2021.2.2及其之前版本),请官网下载新版本
如果不想破解,嫌麻烦。可以找我朋友购买1年的官方正版授权,登录账号就可以使用:
JetBrains 官方正版账号,全家桶全版本全平台都可激活 _
以下为破解教程:
注意:
适用于IntelliJ IDEA 2021.3及其以上 版本
同样适用于其他JetBrains产品,比如PyCharm、DataGrip、Goland、WebStorm等等
适用于Windows、Linux、Mac等操作系统
1. 清空IDEA以前的激活方法
大家可能在网上找了很多破解方法,比如修改Host文件、修改vmoptions配置。安装了补丁插件。这些一定要都删除干净。不然可能会出现一些乱七八糟的问题。
如果没有破解过,直接看下一步。
2. 下载激活脚本
破解补丁下载地址:
JetBrains全家桶激活 - 飞书云文档 (feishu.cn)
img
解释一下文件目录
scripts: 这里存放了激活用到的脚本(windows、mac、linux都有)
vmoptions:IDEA关联的配置文件
注意: 此文件,放到一个安全稳定的位置,之后不要移动,更不要删除。并且路径不要出现中文
3. 运行激活脚本
打开下载文件中的scripts
文件,我们可以看到如下几个文件脚本
img
大家根据自己的操作系统执行对应的脚本
Windows系统: 双击运行 install-current-user.vbs
脚本,为当前用户安装破解补丁。install-all-users.vbs
为所有系统用户安装,不过不太推荐
Mac、Linux系统: 执行install.sh
脚本(Mac 注意给整个文件夹777权限)
与之对应的uninstall xxx
脚本就是卸载补丁的脚本
因为脚本会添加一些配置文件,修改环境变量,所以会被杀毒软件误报,添加信任即可。如果你是在不放心是否安全,可以看一下脚本的源码。
建议先执行uninstall xxxx
脚本,防止以前有过激活信息
双击执行install-xxx
补丁,我们会看到如下的弹窗,意思是:补丁运行可能需要几秒钟,点击确定,然后等待Done的提示框就可以
img
点击确定之后,耐心等待几秒钟或者十几秒。会出现下面的弹窗,代表补丁安装成功
img
4. 输入激活码
运行完破解补丁之后,重启IDEA,一定要重启IDEA!
激活码必须配合补丁使用才会有效!
IDEA激活码:
1 XIZQAN09CR-eyJsaWNlbnNlSWQiOiJYSVpRQU4wOUNSIiwibGljZW5zZWVOYW1lIjoia2lkZHkgaW5zZWFtcyIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb24iOiIiLCJjaGVja0NvbmN1cnJlbnRVc2UiOmZhbHNlLCJwcm9kdWN0cyI6W3siY29kZSI6IlBEQiIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFNJIiwiZmFsbGJhY2tEYXRlIjoiMjAyNS0wOC0wMSIsInBhaWRVcFRvIjoiMjAyNS0wOC0wMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUEMiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBDV01QIiwiZmFsbGJhY2tEYXRlIjoiMjAyNS0wOC0wMSIsInBhaWRVcFRvIjoiMjAyNS0wOC0wMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUkIiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBQUyIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiSUkiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJQR08iLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBTVyIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6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
此激活码仅适用于IDEA
其他软件激活码访问:https://www.955code.com/8857.html
重启完毕之后,复制上方的激活码,粘贴到Activation code
中,显示绿色就代表有效。然后点击activate
如果激活码显示灰色,并且确保破解补丁执行成功,可以重启电脑试试。
之后就看到成功激活到2088年了!
部分版本显示2025年,就是永久激活了!不用太在乎这个时间的。2025也是永久激活
5. 注意事项
脚本文件不要放在中文目录下。必须纯英文路径
适用于2021.3 及以上几个版本。
如果重启IDEA还是无效,请重启电脑之后再输入激活码尝试
脚本文件中的任何一个文件都不要移动,也不要删除
常见问题
1)输入激活码后提示:“key is invalid”(无效key),也就是激活码无效
出现上面的情况后,一般都是工具没有生效,造成激活失败,请仔细看教程,是否遗漏了什么步骤。
也有小伙伴在尝试重启自己电脑后,激活成功。总之,没有激活成功问题比较多,大家可以按其他小伙伴的方式尝试下。
激活须知(必读)
1.本次工具支持2021.3以后版本( 2021.3.1 ,2021.3.2 ,2021.3.3,2022.1,2022.1.1,2022.1.2,2022.1.3,2022.1.4,2022.2 )的IDE使用,请先确认自己IDE版本,其他版本请看这个:https://www.955code.com/2906.html
2.激活前,需退出个人的JB账号,如果之前激活过,请先执行卸载脚本uninstall,在执行安装脚本install
3.激活工具下载后,存放路径不能有空格和汉字 ,并记得要先解压,否则激活失败,提示:“ja-netfilter.jar not found”,(部分Windows用户隐藏了文件后缀名,也会出现找不到jar文件的情况,可以把隐藏的后缀名打开;也有小伙伴是因为文件在微信上接收后,直接操作,那样用户是没有权限的,所以也会提示错误,请创建一个文件夹并移动工具过去);如果提示无法解压,请先安装zip解压工具;激活成功后,不要移动工具位置,更不要删除工具,否则IDE会无法启动。
4.如果之前有破解过,本次想要更新IDE,同时之前破解使用的其他破解工具,需要先删除,并彻底删除idea.64.vmoptions 下工具配置信息
5.激活后,本工具不会对激活的时间做更改,也不会显示2099,但不影响使用,所以不必在意时间
6.该激活工具支持Jetbrains家族下所有IDE(如:IntelliJ IDEA、Pycharm、WebStorm、PHPStorm、GoLand、DataGrip等),同时,支持Windows,Linux,Mac 下使用。
7.如果激活后,进入IDE就退出,提示激活码失效,说明激活工具没有生效,本次激活失败,可以先执行卸载脚本 ,在执行安装脚本,最后尝试重启电脑(尤其是Mac用户,建议执行完脚本重启一下电脑) …
执行脚本提示权限不足
说明下载工具的用户和执行脚本的用户,不是同一个用户,切换一下用户就可以了
执行脚本,没有出现“Done”
如果本地文件和IDE过多,需要耐心等待下,执行时间会比较长,有时候大概5-10分钟,甚至半个小时。
“ja-netfilter.jar not found”
请先解压激活工具 ,如果已经解压,仍提示,请先确认下是否安装JDK环境,另外,部分Windows用户隐藏了文件后缀名,也会出现“ja-netfilter.jar not found”的情况,可以把隐藏的后缀名打开
使用技巧
2024 年 5 月 13 日
下载最新版本 IDEA,2023 版本的,激活。
IDEA2023 的激活与安装(全网最靠谱,最快捷的方式)_idea 激活-CSDN 博客
IDEA 激活码,IDEA 激活码 2022,IDEA 永久激活码_IDEA 激活码 2022 和 2023IDEA 激活码,IDEA 激活码 2022,IDEA 激活码 2023,IDEA 注册码,IDEA 永久破解,Pycharm 激活码,Webstorm 激活码 (ajihuo.com)
常用快捷键
Ctrl + S:保存
Ctrl + A:全选
Ctrl + F:当前页面搜索
Ctrl + Shift + R / 双击 shift:全局搜索
多端口启动项目
在使用 IDEA 作 Java + Spring 全家桶框架后端开发时,经常要多端口跑项目,那么借助 IDEA,这种操作怎样实现呢?
最近在学习 SpringCloud 微服务,就拿其中一个微服务来演示吧
首先,运行 UserService 服务:
如上图所示,该服务已在 8099 端口运行
接下来我们就要实现多端口运行 UserService 服务了
复制一份 UserService 服务运行实例:
点击确认,在 Not Started 下 即可找到复制后的服务:
启动该服务,即可看到 User 在 7099 端口成功运行了:
SpringBoot 版本与 JDK 版本不兼容
今天新构建了一个新的 SpringBoot 项目模板,启动项目时报错:
该项目使用的 SpringBoot 版本为 3.1.2,JDK 版本为 11,
在将 SpringBoot 版本降为 2.7.9 后,项目启动成功了(2023/07/28 晚)
模拟浏览器发送请求
我们在开发过程中,在后台编写好模拟简单的接口后,总是要在网页上输入对应 url,测试该接口能否跑通
然而 IDEA 给我们提供了模拟网页请求的功能:(2023/07/28 晚)
如图所示:
在该页面下,我们可以快速编写 HTTP 请求,POST 或 GET:
1 2 3 4 5 6 7 8 9 10 11 12 13 GET http://localhost:80/api/item?id=99Accept : application/json POST http://localhost:80/api/itemContent-Type : application/x-www-form-urlencoded id=99&content=new-element ### POST http://localhost:80/api/itemContent-Type : application/json {}
有关如何正确处理 HTTP 请求中的参数的问题,日后会更新(2023/08/14 午)
这部分内容 👆 已经在《SpringBoot 配置》中的 SpringMVC 栏目下完成了(2023/10/05 晚)
不仅如此,我们还可以在编写完成 controller 层接口后,模拟浏览器发送请求,快速测试:
这部分的实际运用,可以在《快速启动:开发自己的定制化-Spring-Boot-项目模板》一文中的 快速编写 Controller 层 栏目中了解到(2023/08/14 午)
快速新建 demo
快速构建 Spring Boot 项目
随着 JDK 21
的发布,IDEA 中的构建 Spring Boot 项目也发生了变化:
现在构建新项目,可以看到可选的 JDK 版本只有两个:JDK 17
和 JDK 21
:
由于可选的 Spring Boot
版本只有 3.x.x
版本,且 Spring Boot 3
明确宣布只支持 JDK 17
及以上的版本(2023/12/16 午)
所以新项目如果需要和之前低版本的 Spring Boot
项目合作,就会报错:不支持发行的 17 版本
这就需要我们更旧项目的 JDK
版本了:
导入模块
在 IDEA 中,如何在一个项目中导入一个模块?(2023/08/14 早)
定时任务实现
纯手写单线程循环 1 2 3 4 5 6 7 8 9 10 11 12 public static void timer1 () { new Thread (() -> { while (true ) { System.out.println("定时任务A 当前时间: " + LocalDateTime.now()); try { Thread.sleep(1000 ); } catch (InterruptedException e) { throw new RuntimeException (e); } } }).start(); }
Timer 和他的小伙伴 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public static void timer2 () { Timer timer = new Timer (); System.out.println("1秒后执行任务A,A完成后,等待1秒开始定时执行任务B,当前时间: " + LocalDateTime.now()); timer.schedule(new TimerTask () { @Override public void run () { System.out.println("定时任务A 当前时间: " + LocalDateTime.now()); } }, 1000 ); timer.schedule(new TimerTask () { @Override public void run () { System.out.println("定时任务B 当前时间: " + LocalDateTime.now()); } }, 1000 , 2000 ); }
ScheduledExecutorService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static void timer4 () { ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); System.out.println("2秒后开始执行任务,此刻时间---" + LocalDateTime.now()); scheduledExecutorService.scheduleAtFixedRate(() -> { System.out.println("任务开始---" + LocalDateTime.now()); try { Thread.sleep(2000 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("任务结束---" + LocalDateTime.now()); }, 2000 , 5000 , TimeUnit.MILLISECONDS); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static void timer5 () { ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); System.out.println("2秒后开始执行任务,此刻时间---" + LocalDateTime.now()); scheduledExecutorService.scheduleWithFixedDelay(() -> { System.out.println("任务开始---" + LocalDateTime.now()); try { Thread.sleep(2000 ); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("任务结束---" + LocalDateTime.now()); }, 2000 , 4000 , TimeUnit.MILLISECONDS); }
DelayQueue 延迟任务
DelayQueue 是 JDK 提供的 api,是一个延迟队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Slf4j public class DelayQueueDemo { public static void main (String[] args) { DelayQueue<SanYouTask> sanYouTaskDelayQueue = new DelayQueue <>(); new Thread (() -> { while (true ) { try { SanYouTask sanYouTask = sanYouTaskDelayQueue.take(); log.info("获取到延迟任务:{}" , sanYouTask.getTaskContent()); } catch (Exception e) { } } }).start(); log.info("提交延迟任务" ); sanYouTaskDelayQueue.offer(new SanYouTask ("三友的java日记5s" , 5L )); sanYouTaskDelayQueue.offer(new SanYouTask ("三友的java日记3s" , 3L )); sanYouTaskDelayQueue.offer(new SanYouTask ("三友的java日记8s" , 8L )); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Data public class SanYouTask implements Delayed { private final String taskContent; private final Long triggerTime; public SanYouTask (String taskContent, Long delayTime) { this .taskContent = taskContent; this .triggerTime = System.currentTimeMillis() + delayTime * 1000 ; } @Override public long getDelay (TimeUnit unit) { return unit.convert(triggerTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override public int compareTo (Delayed o) { return this .triggerTime.compareTo(((SanYouTask) o).triggerTime); } }
getDelay
方法返回这个任务还剩多久时间可以执行 ,小于 0 的时候说明可以这个延迟任务到了执行的时间了。
compareTo
这个是对任务排序 的,保证最先到延迟时间的任务排到队列的头。
taskContent :延迟任务的具体的内容
delayTime :延迟时间,秒为单位
实现原理
🍻 offer
方法在提交任务的时候,会通过根据compareTo
的实现对任务进行排序,将最先需要被执行的任务放到队列头。
🍛take
方法获取任务的时候,会拿到队列头部的元素,也就是队列中最早需要被执行的任务,通过 getDelay 返回值判断任务是否需要被立刻执行,如果需要的话,就返回任务,如果不需要就会等待这个任务到延迟时间的剩余时间,当时间到了就会将任务返回。
Spring 提供定时任务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @EnableScheduling @Component public class Timer { @Scheduled(cron = "*/2 * * * * *") public void timer () { System.out.println("哈哈哈哈" ); } }
如果有多个定时任务类,可以考虑把@EnableScheduling 注解添加在启动类上
Cron 表达式
简单地介绍下如何使用吧:(2023/08/25 早)
项目目录显示问题 昨天重构项目之后,项目目录变成了这样,待解决:(2024/01/19 午)
解决了,取消这个显示就行了:
设置技巧 注释对齐
按 Ctrl + / 快捷键 ,就是这样的效果:(2023/10/08 早)
Java 基础
本人太菜,不定时巩固 Java 基础,今天巩固如下操作:(2023/08/14 早)
1 2 3 4 5 6 7 Random random = new Random (); ArrayList<Double> arrayList = new ArrayList <>(); long startTime = System.currentTimeMillis(); for (int i = 0 ; i < 100000 ; i++) { arrayList.add(random.nextDouble()); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Collections.sort(arrayList, new Comparator <Double>() { @Override public int compare (Double o1, Double o2) { return o1.compareTo(o2); } }); Collections.sort(arrayList, (o1, o2) -> { return o1.compareTo(o2); }); Collections.sort(arrayList, (o1, o2) -> o1.compareTo(o2));
1 2 3 4 5 6 7 8 9 arrayList.forEach(item -> { System.out.println(item); }); arrayList.stream().forEach(item -> System.out.println(item)); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 List<Integer> userList = new ArrayList <>(); Random rand = new Random (); for (int i = 0 ; i < 10000 ; i++) { userList.add(rand.nextInt(1000 )); } List<Integer> userList2 = new ArrayList <>(); userList2.addAll(userList); Long startTime1 = System.currentTimeMillis(); userList2.stream().sorted(Comparator.comparing(Integer::intValue)).collect(Collectors.toList()); System.out.println("stream.sort耗时:" + (System.currentTimeMillis() - startTime1) + "ms" ); Long startTime = System.currentTimeMillis(); userList.sort(Comparator.comparing(Integer::intValue)); System.out.println("List.sort()耗时:" + (System.currentTimeMillis() - startTime) + "ms" );
Date/Time API
1 2 3 4 5 6 7 8 9 10 11 12 static void test () { LocalDateTime dateTime = LocalDateTime.now(); System.out.println(dateTime); DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" ); String format = dateTime.format(pattern); System.out.println(format); String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒" )); System.out.println(now); }
1 2 3 4 5 6 7 static void test2 () { Duration between = Duration.between(LocalDate.of(2022 , Month.JULY, 10 ), LocalDate.now()); System.out.println(between); Duration between1 = Duration.between(LocalTime.of(12 , 29 , 10 ), LocalDate.now()); System.out.println(between1); }
Optional 容器类型
ofNullable() 方法:创建一个可能包含 null 值的 Optional 对象(2023/08/18 午)
isPresent() 方法:判断 Optional 中是否存在值。返回 ture 表示存在值 返回 false 表示为 null
get() 方法:如果 Optional 的值存在则返回该值,否则抛出 NoSuchElementException 异常。
1 2 3 4 5 6 7 8 9 static void test3 () { Optional<String> optional = Optional.of("hhh" ); if (optional.isPresent()) { System.out.println(optional.get()); } Optional.of("hhh" ).ifPresent(System.out::println); }
1 2 3 static void test4 (User user) { Optional.ofNullable(user).map(User::getName).ifPresentOrElse(out::println, user != null ? user.setName("ccc" ) : null ); }
BigDecimal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 static void test5 () { BigDecimal dec1 = new BigDecimal ("1.3" ); BigDecimal dec2 = new BigDecimal ("1.3" ); BigDecimal add = dec1.add(dec2); BigDecimal subtract = dec1.subtract(dec2); BigDecimal multiply = dec1.multiply(dec2); BigDecimal divide = dec1.divide(dec2).setScale(3 , RoundingMode.HALF_DOWN); out.println(add); out.println(subtract); out.println(multiply); System.out.println(divide); BigDecimal bigDecimal = divide.stripTrailingZeros(); out.println(bigDecimal); BigDecimal value = new BigDecimal ("1888977466432.1241341341413414" ); double doubleValue = value.doubleValue(); out.println(doubleValue); double doubleValue1 = value.toBigInteger().doubleValue(); out.println(doubleValue1); out.println(add.compareTo(subtract) > 0 ? "add大于sub" : "add小于sub" ); }
数组转字符串
1 2 3 4 List<String> list = Arrays.asList("Apple" , "Banana" , "Cherry" , "Date" , "Elderberry" ); String[] arr = {"0" , "1" , "2" , "3" , "4" , "5" };
如果是 List,则有如下转字符串的方法:(2023/09/20 晚)
1 2 String collect = list.stream().collect(Collectors.joining("," ));
1 2 String join = StringUtils.join(longList, "," );
1 2 3 4 5 6 7 8 StringBuilder sb = new StringBuilder (); for (int i = 0 ; i < list.size(); i++) { sb.append(i); if (i < list.size() - 1 ) { sb.append("," ); } }
1 2 String join = String.join("," , list);
以上方法,转换所消耗的时间越来越少 ,效率越来越高
如果是 String[],则有如下转字符串的方法:(2023/09/20 晚)
1 2 String join = StringUtils.join(longList, "," );
1 2 String join = String.join("," , list);
Java8 中的 Map 函数 computeIfAbsent
如果指定的 key 不存在于 Map 中,那么会执行指定的函数来计算并将结果作为 value 放入到 Map 中。
如果指定的 key 已经存在于 Map 中,则不会执行计算函数,而是直接返回已存在的 value。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import java.util.HashMap;import java.util.Map;public class ComputeIfAbsentExample { public static void main (String[] args) { Map<String, Integer> map = new HashMap <>(); map.put("apple" , 1 ); map.put("banana" , 2 ); map.computeIfAbsent("orange" , key -> { System.out.println("Performing computation for orange" ); return key.length(); }); map.computeIfAbsent("apple" , key -> { System.out.println("Performing computation for apple" ); return key.length(); }); System.out.println(map); } }
computeIfPresent
如果指定的 key 存在于 Map 中,那么会执行指定的函数来计算并将结果作为新的 value 放入到 Map 中。
如果指定的 key 不存在于 Map 中,则不会执行计算函数,什么也不做
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.HashMap;import java.util.Map;public class ComputeIfPresentExample { public static void main (String[] args) { Map<String, Integer> map = new HashMap <>(); map.put("apple" , 1 ); map.put("banana" , 2 ); map.computeIfPresent("apple" , (key, value) -> value * 2 ); map.computeIfPresent("orange" , (key, value) -> value * 2 ); System.out.println(map); } }
compute
而compute()
函数无论旧的 value 是否为null
,都会调用计算函数来计算新的 value,并将计算结果更新到 Map 中。
如果计算结果为null
,则会将对应的 key 从 Map 中移除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.HashMap;import java.util.Map;public class ComputeExample { public static void main (String[] args) { Map<String, Integer> map = new HashMap <>(); map.put("apple" , 1 ); map.put("banana" , null ); map.computeIfPresent("apple" , (key, value) -> value * 2 ); map.computeIfPresent("banana" , (key, value) -> value * 2 ); System.out.println(map); map.compute("apple" , (key, value) -> value + 3 ); map.compute("banana" , (key, value) -> value + 3 ); System.out.println(map); } }
merge
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import java.util.HashMap;import java.util.Map ; public class MergeExample { public static void main(String [] args) { Map <String , Integer> map1 = new HashMap<>(); map1.put("apple" , 1 ); map1.put("banana" , 2 ); Map <String , Integer> map2 = new HashMap<>(); map2.put("apple" , 5 ); map2.put("orange" , 3 ); map2.forEach((key, value) -> { map1.merge(key, value, (oldValue, newValue) -> oldValue + newValue); }) ; System .out .println (map1) ; // 输出: {orange =3, apple =6, banana =2} } }
getOrDefalut
当 key 存在时,取对应 value,否则取默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static int firstUniqChar (String s) { if (s == null || s.length() == 0 ) { return 0 ; } Map<Character, Integer> frequency = new HashMap <Character, Integer>(); for (int i = 0 ; i < s.length(); ++i) { char ch = s.charAt(i); frequency.put(ch, frequency.getOrDefault(ch, 0 ) + 1 ); } for (int i = 0 ; i < s.length(); ++i) { if (frequency.get(s.charAt(i)) == 1 ) { return i; } } return -1 ; }
putIfAbsent
与 put 的区别:如果有重复 key,保存的是最早存入的键值对 (2023/10/08 早)
forEach Java8 中的 Stream 流函数 groupingBy
将集合中的元素,按某个属性进行分组 ,返回的结果 是一个 Map 集合 (2023/10/08 早)
1 2 3 4 5 6 7 8 9 public class Person { private int age; private String name; public Person (int age, String name) { this .age = age; this .name = name; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class GroupingByExample { public static void main (String[] args) { List<Person> people = new ArrayList <>(); people.add(new Person (25 , "Alice" )); people.add(new Person (30 , "Bob" )); people.add(new Person (25 , "Charlie" )); people.add(new Person (40 , "David" )); people.add(new Person (30 , "Emily" )); Map<Integer, List<Person>> groups = people.stream() .collect(Collectors.groupingBy(Person::getAge)); System.out.println(groups); } }
泛型理解
学习 Java 泛型:(2023/10/13 晚)
泛型类
泛型接口
泛型方法:返回值、入参位置、方法体中
个人感受:泛型很好理解:我们经常讲到一个对象实例的就是以类作为模板创建的,那么也可以讲一个普通类可以以泛型类作为模板;那么泛型是用来干嘛的呢,我们为什么要使用泛型呢?其实,所有的泛型类在编译后生成的字节码与普通类无异,因为在编译前,所有泛型类型就被擦除了。所以我们可以把泛型看作一个语法糖,将类型转换的校验提前在编译时,减少类型转换错误的发生,使编写的程序更加具有健壮性。
我觉得以下这段总结更妙:
泛型是 Java 语言中的一项强大的特性,它允许在编译时指定类、接口或方法的参数类型,从而在编译阶段就能够进行类型检查。这样可以减少类型转换的错误,并提高代码的安全性和可读性。
通过使用泛型,我们可以在编译时捕捉到一些类型错误,而不是在运行时才发现,这样可以避免一些潜在的 bug。泛型还可以增加代码的可重用性和灵活性,因为泛型类、接口和方法可以用于多种不同的类型,而无需针对每一种类型单独编写或重复编写相似的代码。
总的来说,通过使用泛型,我们可以在编写 Java 代码时更好地约束和使用类型信息,减少类型错误,提高代码的可读性和健壮性。
了解泛型的实现原理,理解泛型的使用方式,更加加深了我们对 Java 语言的理解
良心插件 carbon-now-sh
在弹出的网页页面中,可以调整代码风格,点击导出就下载成功了~
2025 年 1 月 8 日
简单调整一下代码样式,可直接复制图片,节省出导出这一步的时间。
MybatisX-Genetator
MybatisX-Genetator:代码自动生成器
连接到数据库后,在一个表右键菜单点击 MybatisX-Genetator:(2023/08/20 晚)
点击 Finish,直接生成 domain、service、serviceImpl、mapper、mapperXml:
GenerateAllSetter
这是一款快速生成对象的 getter、setter 方法 的插件,对日常的代码开发很有帮助 (2023/10/05 晚)
我们定义一个 User 对象 ,右键,即可快速生成该对象的 geeter、setter 方法 :
我在开发项目的过程中,转换 entity 为 对应 VO 对象 时,使用该插件居多:(2023/10/05 晚)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public List<TeamVO> getTeamVOByTeam (List<Team> teamList) { return teamList.stream().map(team -> { Long userId = team.getUserId(); String userName = userService.getById(userId).getUsername(); TeamVO teamVO = new TeamVO (); teamVO.setId(team.getId()); teamVO.setName(team.getName()); teamVO.setDescription(team.getDescription()); teamVO.setMaxNum(team.getMaxNum()); teamVO.setUserName(userName); teamVO.setImgUrl(team.getImgUrl()); teamVO.setJoinNum(team.getJoinNum()); teamVO.setStatus(team.getStatus()); teamVO.setExpireTime(team.getExpireTime()); teamVO.setCreateTime(team.getCreateTime()); teamVO.setUpdateTime(team.getUpdateTime()); teamVO.setIsDelete(team.getIsDelete()); teamVO.setAnnouncement(team.getAnnouncement()); return teamVO; }).collect(Collectors.toList()); }
String Manipulation
可以实现快速将选定字符串转换为大写:
Statistic
2025 年 1 月 8 日
总结