Java后端编程语言进阶篇

news2024/11/14 2:54:33

第一章 函数式接口

函数式接口是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;
        }
    }

    @Test
    public 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() {
            @Override
            public 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>() {
            @Override
            public Integer call() throws Exception {
                subtract();
                System.out.println(Thread.currentThread().getName()+",当前count为:"+count);
                return count;
            }
        }).get();

        Integer result2 = executor.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                subtract();
                System.out.println(Thread.currentThread().getName()+",当前count为:"+count);
                return count;
            }
        }).get();

        //终止线程池
        executor.shutdown();
    }
}

待完善…

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

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

相关文章

linux-L3-linux 复制文件

linux 中要将文件file1.txt复制到目录dir中&#xff0c;可以使用以下命令 cp file1.txt dir/复制文件 cp /path/to/source/file /path/to/destination移动 mv /path/to/source/file /path/to/destination复制文件夹内的文件 cp -a /path/to/source/file /path/to/destinati…

孟德尔随机化分析和GWAS分析有什么区别?

大家好&#xff0c;我是邓飞。 最近一直在研究孟德尔随机化分析&#xff0c;已经从概念到实操了&#xff0c;程序已经跑通了&#xff0c;很开心。这几天写的博客&#xff1a; 孟德尔随机化的术语理解 从一篇孟德尔随机化文章看MR常见结果形式 对于GWAS分析&#xff0c;从原…

LRELHLNNN;亲水性抗肝纤维化多肽作为基础肽;I型胶原蛋白靶向肽;九肽LRELHLNNN

【LRELHLNNN 简介】 LRELHLNNN是一种多肽&#xff0c;它能够选择性地结合到I型胶原蛋白&#xff0c;具有亲和力为170 nM。LRELHLNNN是由9个氨基酸组成&#xff0c;其氨基酸序列为H-Leu-Arg-Glu-Leu-His-Leu-Asn-Asn-Asn-OH。LRELHLNNN因其与I型胶原蛋白的高亲和力而在生物医学领…

密码学---黄道十二宫

✨简单理解的概念&#xff1a;是一种换位密码。 &#x1f380;破解需要用到对角线的方式&#xff1a;第一个H&#xff0c;先向下移动1位&#xff0c;再向右移动2位&#xff0c;依次类推。 &#x1f380;接着对对角线重新排列&#xff0c;就能得到一段有序的代码 &#x1f380; …

玩机搞机-----如何简单的使用ADB指令来卸载和冻结系统应用 无需root权限 详细操作图示教程

同类博文&#xff1a; 玩机搞机---卸载内置软件 无root权限卸载不需要的软件 安全卸载_无需root卸载彻底内置软件-CSDN博客 在很多时候我们需要卸载一些系统级的app。但如果直接手机端进行卸载的话。是无法正常卸载的。其实我们可以通过有些成品工具或者完全靠ADB指令来进行卸…

网红酒店|基于java的网红酒店预定系统(源码+数据库+文档)

酒店预定|网红酒店|网红酒店预定系统 目录 基于java的网红酒店预定系统 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&am…

4×4矩阵键盘详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.工作原理介绍 三、程序设计 main.c文件 button4_4.h文件 button4_4.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 ​​​​​矩阵键盘&#xff0c;又称为行列式键盘&#xff0c;是用4条I/O线作为行线&#xff0c;4…

【四范式】浅谈NLP发展的四个范式

自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;是计算机科学&#xff0c;人工智能&#xff0c;语言学关于计算机和人类自然语言之间的相互作用的领域&#xff0c;是计算机科学领域与人工智能领域中的一个重要方向。NLP发展到今天已经进入到了…

[Python学习日记-19] 细讲数据类型——集合

[Python学习日记-19] 细讲数据类型——集合 简介 集合的创建 集合的增删查 集合的循环 集合的去重 集合的关系运算 简介 在前面我们学习到了列表、元组、字符串、字典这几种数据类型&#xff0c;在 Python 中还有最后一种数据类型&#xff0c;那就是集合&#xff0c;下面…

Cloudflare Pages 部署 Next.js 应用教程

Cloudflare Pages 部署 Next.js 应用教程 本教程将指导你如何将现有的 Next.js 应用部署到 Cloudflare Pages。 准备工作 安装部署依赖 首先,安装 cloudflare/next-on-pages: npm install --save-dev cloudflare/next-on-pages添加 wrangler.toml 配置文件 在项目根目录创建 …

如何删除git提交记录

今天在提交github时&#xff0c;不小心提交了敏感信息&#xff0c; 不要问我提交了啥&#xff0c;问就是不知道 查了下资料&#xff0c;终于找到简单粗暴的方式来删除提交记录。方法如下 git reset --soft HEAD~i i代表要恢复到多少次提交前的状态&#xff0c;如指定i 2&…

GD32F4开发 -- SEGGER RTT移植

FreeRTOS移植了&#xff0c;我将SEGGER RTT移植和FATFS也一并移植进去得了。 参看&#xff1a;GD32F4开发 – JLink使用 这里面其实已经讲了怎么移植了。 一、移植 直接将整个 RTT 文件夹加入工程 将其拷贝到我的工程&#xff1a; 二、创建 RTT 分组 工程目录如下&#xf…

微波无源器件 功分器2 用于双极化应用的新型宽带圆波导四路功分

摘要&#xff1a; 提出了一种适用于多级()波束形成网络高度紧凑和有效的双模功。圆波导双极化通过使用一个对称4:1的十字转门拓扑和有策略的腔体谐振抑制器来实现理论35dB的交叉极化隔离的高于20%的带宽。对于一个Ku波段(10.5-13GHz)的双模四路功分器的实测验证被提出了&#x…

2024重症医学科常用评估量表汇总,附操作步骤与评定标准!

常笑医学整理了8个重症医学科常用的评估量表&#xff0c;包括院前指数评估、多脏器功能障碍评分、急性生理学与慢性健康状况评分等。这些量表在常笑医学网均支持在线评估、下载和创建项目使用。 01 院前指数评估 &#xff08;完整量表请点击量表名称查看&#xff09; 院前指数…

音频芯片DP7344兼容CS4344低成本方案双通道24位DA转换器

产品简介 DP7344 是一款完整的 2 通道输出数模转换芯片&#xff0c;内含插值滤波器、Multi-Bit 数模转换器、输出模拟滤波器&#xff0c;并支持大部分的音频数据格式。 DP7344 基于一个带线性模拟低通滤波器的四阶 Multi-BitΔ∑调制器&#xff0c;自动检测信号频率和主时钟频率…

班组建设中如何避免团队协作的问题?

在班组建设的广阔天地里&#xff0c;团队协作无疑是推动项目进展、提升工作效率的基石。然而&#xff0c;在实际操作中&#xff0c;团队协作往往伴随着一系列复杂而微妙的问题&#xff0c;这些问题若得不到妥善解决&#xff0c;便会成为阻碍团队前进的绊脚石。本文&#xff0c;…

AMD CMD UMD CommonJs ESM 的历史和区别

这几个东西都是用于定义模块规范的。有些资料会提及到这些概念&#xff0c;不理清楚非常容易困惑。 ESM&#xff08;ES Module&#xff09; 这个实际上我们是最熟悉的&#xff0c;就是ES6的模块功能。出的最晚&#xff0c;因为是官方出品&#xff0c;所以大势所趋&#xff0c…

Qt 开发:深入详解 Qt 的信号与槽机制——彻底搞懂QT信号与槽

一、概念 Qt 的信号与槽&#xff08;Signals and Slots&#xff09;机制是一个用于对象间通信的核心特性。这个机制使得对象能以松散耦合的方式进行通信&#xff0c;从而提升了代码的模块化和可维护性。 信号&#xff08;Signal&#xff09;&#xff1a;对象状态的变化或事件…

C++:内部类,匿名对象,操作符new与delete

一.内部类 1.如果一个类定义在另一个类的内部&#xff0c;这个内部类就叫做内部类。内部类是一个独立的类&#xff0c;跟定义在全局相比&#xff0c;他只是受外部类类域限制和访问限定符限制&#xff0c;所以外部类定义的对象中不包含内部类。 2.内部类默认是外部类的友元类。…

基于Java+Mysql实现(web)大型企业管理系统

技术报告 第一章 系统概述 包括用户管理、权限管理、软件项目管理、软件模块管理、测试用例管理、测试任务分配、bug管理等功能。实现公司不同部门间团队协作&#xff0c;管理人员也能够更加有效的把控系统开发的进度。 本实验综合应用JavaWeb编程中的Servlet&#xff0c;JS…