Java后端编程语言进阶篇

第一章 函数式接口

函数式接口是Java 8中引入的一个新特性,只包含一个抽象方法的接口。

函数式接口可以使用Lambda表达式来实现,从而实现函数式编程的特性。

使用 @FunctionalInterface标识接口是函数式接口,编译器才会检查接口是否符合函数式接口的定义。

四大核心函数式接口
在这里插入图片描述

自定义函数式接口

@FunctionalInterface
interface MyFunction {int calculate(int a, int b); // 抽象方法
}

实现函数式接口

public class Main {public static void main(String[] args) {// 使用Lambda表达式实现函数式接口的抽象方法MyFunction add = (a, b) -> a + b;System.out.println("Addition: " + add.calculate(3, 5));}
}

第二章 Lambda表达式

Lambda表达式是在Java 8引入的,Lambda表达式是一种匿名函数,可以作为参数传递给方法存储在变量中,使用Lambda表达式可以简化代码编写,使代码更加简洁和易读。

基本语法

Lambda表达式的基本语法包括参数列表箭头符号方法体

(params) -> expression 或者 {statements;}
  • params :参数列表,可以为空或非空。
  • -> :箭头符号,将参数列表和Lambda表达式的主体分开。
  • expression :单行Lambda表达式的返回值表达式
  • {statements;} :Lambda表达式的方法体,可以是一个表达式或一段代码块

第三章 方法引用

方法引用是一种简化Lambda表达式的语法,可以直接引用已有方法的实现,是Java8的新特性之一。

(1)引用类方法

格式:类名::静态方法

示例代码:

List<String> list = new ArrayList<>();
list.add("11");
list.add("22");
Integer result = list.stream().map(Integer::parseInt).reduce(0, Integer::sum);
System.out.println(result);

(2)引用成员方法

格式:对象::成员方法

List<User> userList = userService.list();
userList.stream().map(User::getName).forEach(item->{System.out.println(item);
});

(3)引用构造器

格式:类名::new

第四章 Stream流式编程

Java Stream流是 Java 8 引入的一个新的抽象概念,代表着一种处理数据的序列,比如对 Stream 中的元素进行数据转换、过滤、映射、聚合等操作,从而实现对数据的处理和操作。 函数式编程

java.util.stream

Stream 对象是一种一次性使用的对象,只能被消费一次,一旦对 Stream 执行了终止操作(如收集结果、遍历元素),Stream 就会被关闭,后续无法再使用。

Stream流式操作主要有 3 个步骤:

  • 创建Stream对象:通过一些数据源创建流对象
  • 中间操作:对数据源的数据进行处理(过滤、排序等)
  • 终止操作:一旦执行终止操作, 就执行中间的链式操作,并产生结果。

在Java中,Stream流分为两种类型:

  • 流(Stream):表示顺序流,按照数据源的顺序进行操作,适用于串行操作。

  • 并行流(ParallelStream):表示并行流,可以同时对数据源的多个元素进行操作,适用于并行计算。

    注意线程安全和性能问题。

4.1 创建 Stream 对象

(1)数据源为集合:调用集合的 stream()方法来创建Stream 对象

(2)数据源为数组:Arrays类的 stream()方法

(3)Stream.of()创建 数据已知

(4)Stream.builder()创建 数据未知

NOTE:Stream流是不会改变源对象的,而是返回一个新的持有结果的Stream。

4.2 中间操作

filter(Predicate)筛选

根据给定的条件(Predicate)过滤流中的元素,只保留符合条件的元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream().filter(num -> num % 2 == 0).collect(Collectors.toList()); //[2, 4]

map(Function)映射

将流中的每个元素映射为另一个元素,生成一个新的流。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<Integer> nameLengths = names.stream().map(String::length)  //映射为长度.collect(Collectors.toList()); //  [5, 3, 7]

sorted()排序

对流中的元素进行排序,默认是自然顺序排序,也可以传入Comparator进行自定义排序。

List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6, 5);
List<Integer> sortedNumbers = numbers.stream().sorted().collect(Collectors.toList()); // [1, 1, 2, 3, 4, 5, 5, 6, 9]

distinct()去重

去除流中重复的元素,得到一个去重后的新流。

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3, 4, 4, 4, 4);
List<Integer> distinctNumbers = numbers.stream().distinct().collect(Collectors.toList());// [1, 2, 3, 4]

limit(long)截取

截取流中的前几个元素,生成一个新的流。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream().limit(3).collect(Collectors.toList());// [1, 2, 3]

skip(long)跳过

跳过流中的前几个元素,生成一个新的流。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream().skip(2).collect(Collectors.toList());// [3, 4, 5]

4.3 中止操作

Stream的终止操作用于触发流的计算(延迟执行)并得到最终的结果

forEach(Consumer)

对流中的每个元素执行指定的操作

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);//控制台输出每个字符串

reduce(BinaryOperator)

对流中的元素进行归约操作,得到一个最终的结果。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, Integer::sum); // 对流中的元素求和

count()

返回流中元素的个数

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
long count = names.stream().count();// 返回3

anyMatch(Predicate)

判断流中是否存在任意一个元素满足给定条件

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEvenNumber = numbers.stream().anyMatch(num -> num % 2 == 0);// 返回true

allMatch(Predicate)

判断流中的所有元素是否都满足给定条件

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allPositive = numbers.stream().allMatch(num -> num > 0);// 返回true,因为流中所有元素都是正数

第五章 线程池

线程池(Thread Pool)是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如MySQL。

池化,顾名思义,是为了最大化收益并最小化风险,而将资源统一在一起管理的一种思想。

(1)内存池(Memory Pooling):预先申请内存,提升申请内存速度,减少内存碎片。

(2)连接池(Connection Pooling):预先申请数据库连接,提升申请连接的速度,降低系统的开销。

(3)实例池(Object Pooling):循环使用对象,减少资源在初始化和释放时的昂贵损耗。

线程池的优点:

  • 降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
  • 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
  • 提高线程的可管理性:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
  • 提供更多更强大的功能:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如延时定时线程池ScheduledThreadPoolExecutor,就允许任务延期执行或定期执行。

Java中的线程池核心实现类是ThreadPoolExecutor

在这里插入图片描述

构造器如下:

 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {...}

参数说明:

  • corePoolSize : 线程池的核心线程数量。任务队列未达到队列容量时,最大可以同时运行的线程数量。

  • maximumPoolSize :线程池的最大线程数。任务队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。

  • keepAliveTime:线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime才会被回收销毁。

  • unit : keepAliveTime 参数的时间单位。

  • workQueue: 任务队列,用来储存等待执行任务的队列。新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。

  • threadFactory :线程工厂,用来创建线程,一般默认即可。

  • handler :拒绝策略。当提交的任务过多而不能及时处理时,可以定制策略来处理任务。

线程池思想

在这里插入图片描述

阻塞队列

新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。

LinkedBlockingQueue(无界队列)

SynchronousQueue(同步队列)

DelayedWorkQueue(延迟阻塞队列)

四种拒绝策略

如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任务时,ThreadPoolExecutor 定义一些策略:

(1)ThreadPoolExecutor.AbortPolicy:抛出 RejectedExecutionException来拒绝新任务的处理。

(2)ThreadPoolExecutor.CallerRunsPolicy:调用执行自己的线程运行任务,也就是直接在调用execute方法的线程中运行(run)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。

(3)ThreadPoolExecutor.DiscardPolicy:不处理新任务,直接丢弃掉。

(4)ThreadPoolExecutor.DiscardOldestPolicy:此策略将丢弃最早的未处理的任务请求。

线程安全的方式

避免共享状态

如果可能,最好是完全避免共享状态。可以设计无状态类或者确保线程之间没有数据共享。

不可变对象

不可变对象一旦创建就不可以被更改。因此在多线程环境中,不可变对象是线程安全的。

例如,使用 final 关键字声明的对象。

synchronized关键字

同步方法同步代码块

Lock

java.util.concurrent.locks.Lock

分布式锁

如果是在单机的情况下,使用synchronizedLock保证线程安全是没有问题的。

如果在分布式的环境中,即某个应用如果部署了多个节点,每一个节点可以使用synchronizedLock保证线程

安全,但不同的节点之间,没法保证线程安全。解决方式:分布式锁

分布式锁有很多种,比如:数据库分布式锁,zookeeper分布式锁,redis分布式锁等。

volatile

需求:只要求多个线程间的可见性,不要求原子性

可见性是指当一个线程修改了共享变量的值,这种修改对于其他线程是立即可见的。

原子性是指一个操作或者多个操作要么全部完成,要么全部不完成。

线程安全集合

JDK提供了能够保证线程安全的集合,比如:ConcurrentHashMap、ArrayBlockingQueue等等。

CAS比较再交换

CAS内部包含了四个值:旧数据期望数据新数据地址,比较旧数据 和 期望的数据,如果一样的话,就把旧数据改成新数据。如果不一样的话,当前线程不断自旋,一直到成功为止。

原子类

通过使用 java.util.concurrent.atomic 包中的原子类(如 AtomicInteger, AtomicLong等),针对基本数据类型提供了线程安全的操作。保证可见性。

本质是:volatile关键字

高级同步工具

java.util.concurrent 包提供了高级的同步工具,比如 CountDownLatch等。

示例代码

需要多运行几次,才能看到效果。

@SpringBootTest
public class ThreadTest {//共享变量,存在线程安全问题private static Integer count=10;//原子类,底层volatile关键字,保证可见性private static AtomicInteger count2 = new AtomicInteger(10);public static void subtract(){synchronized (ThreadTest.class){count-=1;}}@Testpublic void testThreadPool() throws Exception{int corePoolSize=4;int maximumPoolSize=6;int capacity = 2;long keepAliveTime = 1L;ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize,maximumPoolSize, keepAliveTime, TimeUnit.SECONDS,new ArrayBlockingQueue<>(capacity),new ThreadPoolExecutor.CallerRunsPolicy());executor.execute(new Runnable() {@Overridepublic void run() {subtract();System.out.println(Thread.currentThread().getName()+",当前count为:"+count);}});executor.execute(() -> {subtract();System.out.println(Thread.currentThread().getName()+",当前count为:"+count);});Integer result1 = executor.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {subtract();System.out.println(Thread.currentThread().getName()+",当前count为:"+count);return count;}}).get();Integer result2 = executor.submit(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {subtract();System.out.println(Thread.currentThread().getName()+",当前count为:"+count);return count;}}).get();//终止线程池executor.shutdown();}
}

待完善…

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

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

相关文章

Qt 实现自定义截图工具

目录 Qt 实现自定义截图工具实现效果图PrintScreen 类介绍PrintScreen 类的主要特性 逐步实现第一步&#xff1a;类定义第二步&#xff1a;初始化截图窗口第三步&#xff1a;处理鼠标事件第四步&#xff1a;计算截图区域第五步&#xff1a;捕获和保存图像 完整代码PrintScreen.…

《程序猿之设计模式实战 · 池化思想》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

LSS如何做深度和语义预测

get_cam_feats() 先来看看代码: def get_cam_feats(self, x):"""Return B x N x D x H/downsample x W/downsample x C"""B, N

解锁编程潜力,从掌握GitHub开始

目录&#xff1a; 一、搜索开源项目 1、什么是Git 2、Github常用词含义 3、一个完整的项目界面 4、使用Github搜索项目 1&#xff09;in关键词 2&#xff09;star或fork数量去查找 3&#xff09;awesome加强搜索 二、访问速度慢的解决 1、使用网易UU加速器 2、使用…

基于SSM的大学新生报到系统+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

VSCode创建C++项目和编译多文件

前言 在刚安装好VSCode后&#xff0c;我简单尝试了仅main.cpp单文件编译代码&#xff0c;没有问题&#xff0c;但是当我尝试多文件编译时&#xff0c;就出现了无法识别cpp文件。 内容 创建项目 首先点击左上角“文件”&#xff1b;在菜单中选择“打开文件夹”&#xff1b;在…

【Elasticsearch系列二】安装 Kibana

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

ClickHouse 24.8 LTS 版本发布说明

本文字数&#xff1a;13885&#xff1b;估计阅读时间&#xff1a;35 分钟 作者&#xff1a;ClickHouse Team 本文在公众号【ClickHouseInc】首发 时间飞逝&#xff0c;又到了新版本发布的时刻&#xff01; 发布概要 本次ClickHouse 24.8 版本包含了19个新功能&#x1f381;、18…

基于51单片机的16X16点阵显示屏proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1JQ225NSKweqf1Zlad_f1Mw 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectro…

管家婆云辉煌手机端怎么连接蓝牙打印机?

管家婆云辉煌手机端可以连接蓝牙打印机&#xff0c;这样手机可以发送打印任务到蓝牙打印机&#xff0c;完成打印任务。具体的设置步骤如下&#xff1a; 一、首先完成手机和蓝牙打印机配对&#xff0c;打开蓝牙打印机后。手机开启蓝牙和定位服务 点击手机设置&#xff0c;进入手…

分类预测|基于差分优化DE-支持向量机数据分类预测完整Matlab程序 DE-SVM

分类预测|基于差分优化DE-支持向量机数据分类预测完整Matlab程序 DE-SVM 文章目录 一、基本原理DE-SVM 分类预测原理和流程总结 二、实验结果三、核心代码四、代码获取五、总结 一、基本原理 DE-SVM 分类预测原理和流程 1. 差分进化优化算法&#xff08;DE&#xff09; 原理…

【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署

【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署前言Windows平台搭建依赖环境模型转换--pytorch转onnxONN…

走进低代码表单开发(一):可视化表单数据源设计

在前文&#xff0c;我们已对勤研低代码平台的报表功能做了详细介绍。接下来&#xff0c;让我们深入探究低代码开发中最为常用的表单设计功能。一个完整的应用是由众多表单组合而成的&#xff0c;所以高效的表单设计在开发过程中起着至关重要的作用。让我们一同了解勤研低代码开…

[网络]http/https的简单认识

文章目录 一. 什么是http二. http协议工作过程三. http协议格式1. 抓包工具fiddler2. http请求报文3. http响应报文 一. 什么是http HTTP (全称为 “超⽂本传输协议”) 是⼀种应⽤⾮常⼴泛的 应⽤层协议 HTTP 诞⽣与1991年. ⽬前已经发展为最主流使⽤的⼀种应⽤层协议 HTTP 往…

FPGA实现串口升级及MultiBoot(四)MultiBoot简介

缩略词索引&#xff1a; K7:Kintex 7V7:Vertex 7A7:Artix 7 我们在正常升级的过程&#xff08;只使用一个位流文件&#xff09;&#xff0c;假如&#xff1a;&#xff08;1&#xff09;因为干扰通信模块收到了一个错误位&#xff1b;&#xff08;2&#xff09;或者烧写进FLASH时…

《深度学习》—— 神经网络模型中的损失函数及正则化惩罚和梯度下降

文章目录 前言一、损失函数二、正则化惩罚三、梯度下降 前言 在神经网络中&#xff0c;损失函数、正则化惩罚和梯度下降是三个关键的概念&#xff0c;它们共同作用于网络的训练过程&#xff0c;以提升网络的性能和泛化能力。神经网络模型结构如下图所示&#xff1a; 在构建好一…

LCSS—最长回文子序列

思路分析 关于”回文串“的问题&#xff0c;是面试中常见的&#xff0c;本文提升难度&#xff0c;讲一讲”最长回文子序列“问题&#xff0c;题目很好理解&#xff1a; 输入一个字符串 s&#xff0c;请找出 s 中的最长回文子序列长度。 比如输入 s"aecda"&#xff0c…

【AI-18】Adam和SGD优化算法比较

Adam&#xff08;Adaptive Moment Estimation&#xff09;和 SGD&#xff08;Stochastic Gradient Descent&#xff0c;随机梯度下降&#xff09;是两种常见的优化算法&#xff0c;它们在不同方面有各自的特点。 一、算法原理 SGD&#xff1a; 通过计算损失函数关于每个样本的…

S7-1500T分布式同步功能

1. 功能描述工控人加入PLC工业自动化精英社群 在一些实际应用中&#xff0c;会需要很多轴进行同步运行&#xff0c;如印刷机、纸尿裤生产线等。由于一个 PLC 的运动控制资源有限&#xff0c;控制轴的数量也是有限的&#xff0c;就会需要多个 PLC 间协调实现轴工艺对象的跨CPU的…