8个你必须知道的Java8新特性,让你的代码变得优雅!

news2024/11/24 2:10:46

Java 8 是一次重大的发行版更新,引入了大量新特性和改进,以下是 Java 8 的主要特性:

文章目录

        • Java 8 是一次重大的发行版更新,引入了大量新特性和改进,以下是 Java 8 的主要特性:
          • 1.Lambda 表达式
          • 2.Stream API
          • 3.Date/Time API
          • 4.接口中的默认方法:
          • 5.函数式接口
          • 6.方法引用(::)
          • 7.Optional 容器类型
          • 8.Parallel Streams

在这里插入图片描述

1.Lambda 表达式

Lambda 允许在代码中直接定义匿名函数,简化了对函数式编程的支持。

// Lambda 表达式示例
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
nums.stream()
    .filter(num -> num % 2 == 0) // 过滤偶数
    .map(num -> num * 2) // 将每个元素乘以 2
    .forEach(System.out::println); // 打印结果
2.Stream API

通过 Stream API 可以轻松处理集合和数组等数据结构,提高了代码的可读性和可维护性。以下是Stream API中常用的方法:

  • filter(Predicate predicate):过滤出所有符合条件的元素。

  • map(Function function):将元素转换为另一种类型。

  • flatMap(Function function):将嵌套的多个流扁平化成一个流。

  • distinct():去除重复元素。

  • sorted():排序。

  • boxed:将基本数据类型转换为对应的包装类类型。

  • peek(Consumer action):对每个元素执行指定的操作。

  • limit(long maxSize):限制元素数量。

  • skip(long n):跳过前 n 个元素。

  • forEach(Consumer action):对每个元素执行指定的操作。

  • count():计数。

  • reduce(BinaryOperator accumulator):将所有元素归约成一个结果。

  • collect(Collector collector):收集结果到一个集合中。

  • allMatch(Predicate predicate):判断是否所有元素都符合给定条件。

  • anyMatch(Predicate predicate):判断是否任何一个元素符合给定条件。

  • noneMatch(Predicate predicate):判断是否没有任何元素符合给定条件。

  • findFirst():返回第一个元素。

  • findAny():返回任意一个元素。

  • 这些操作可以通过链式调用的方式进行组合,形成一个完整的流处理链。如下是一个简单的例子:

    List<String> list = Arrays.asList("apple", "banana", "orange", "peach");long count = list.stream()  // 将 List 转换为 Stream
                     .filter(str -> str.startsWith("a"))  // 过滤出以 a 开头的字符串
                     .map(String::toUpperCase)  // 转换为大写
                     .count();  // 统计数量System.out.println(count);  // 输出结果:1
    
    3.Date/Time API

    在 Java 8 中引入了全新的日期时间处理类库,使得处理日期时间变得更加方便和易于理解。以下是 java.time 包中最重要的一些类:

    • LocalDate:表示日期,如 2022 年 5 月 15 日。
    • LocalTime:表示时间,如 13:45:30。
    • LocalDateTime:代表日期和时间,比如 2022 年 5 月 15 日 13:45:30。
    • ZonedDateTime:代表带有时区的日期时间,在上述所有日期时间类型的基础上,还提供了时区信息。
    • Duration:在两个时间点之间表示时间量。
    • Period:在两个日期之间表示天、周、月或年的数量。
    • DateTimeFormatter:可以将日期时间对象按照指定的格式进行格式化或者解析。
    • 以下是使用 Java 8 新的日期时间 API 的一些示例代码:
    // 创建 LocalDate 对象,表示当前日期
    LocalDate localDate = LocalDate.now();// 创建 LocalTime 对象,表示下午 2:30 这个时间点
    LocalTime localTime = LocalTime.of(14, 30, 0);// 创建 LocalDateTime 对象,表示 2022 年 6 月 1 日上午 12:30 这个日期时间。
    LocalDateTime localDateTime = LocalDateTime.of(2022, Month.JUNE, 1, 12, 30);// 在当前日期时间上加上一小时
    localDateTime = localDateTime.plusHours(1L);// 创建 Duration 对象,并计算两个时间点之间的时间量
    Duration duration = Duration.between(localTime, LocalTime.now());// 使用 DateTimeFormatter 对象对日期时间进行格式化
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    String formattedDateTime = localDateTime.format(dateTimeFormatter);
    
    4.接口中的默认方法:

    ​ 允许在接口中添加默认方法的实现,大大提高了接口的灵活性和扩展性。需要注意的是,这些接口默认方法并不是强制实现的,也可以被继承类或实现类所覆盖和重写。但在没有其他需求时,通过使用默认方法,可以大幅简化代码,并保证 API 的向后兼容性。如下Collection 接口中新增的 stream()、parallelStream() 和 removeIf() 等默认方法

    public interface Collection<E> extends Iterable<E> {
        default Stream<E> stream() {
            return StreamSupport.stream(spliterator(), false);
        }
        default Stream<E> parallelStream() {
            return StreamSupport.stream(spliterator(), true);
        }
        default boolean removeIf(Predicate<? super E> filter) {
            Objects.requireNonNull(filter);
            boolean removed = false;
            final Iterator<E> each = iterator();
            while (each.hasNext()) {
                if (filter.test(each.next())) {
                    each.remove();
                    removed = true;
                }
            }
            return removed;
        }
    }
    
    5.函数式接口

    函数式接口非常适合用于Lambda表达式和方法引用,因为它们可以将这些功能作为参数传递给方法或返回值,从而使代码更简洁、更具可读性。许多Java内置的函数式接口都在java.util.function包中定义,其中几个常用的接口如下:

    Function:接受一个参数并产生结果的函数。

    // 接收一个字符串类型参数并返回对应整数长度值
    Function<String, Integer> stringToLength = str -> str.length();
    System.out.println(stringToLength.apply("Hello World!"));
    // 输出结果:12
    

Predicate: 接受一个参数并返回一个布尔值,表示断言函数。

// 判断一个数字是否是奇数
Predicate<Integer> isOdd = number -> number % 2 != 0;
System.out.println(isOdd.test(5));
// 输出结果:true

Consumer`:接受一个参数不返回结果,表示消费者函数。

// 输出一个字符串的大写形式
Consumer<String> printStringInUpperCase = str -> System.out.println(str.toUpperCase());
printStringInUpperCase.accept("hello world!");
// 输出结果:HELLO WORLD!

Supplier:提供一个无参构造函数,返回任意类型结果。

// 产生随机数
Supplier<Integer> randomIntegerSupplier = () -> (int) (Math.random() * 100);
System.out.println(randomIntegerSupplier.get());
// 输出结果:一个0~99之间的随机整数
6.方法引用(:😃

Java 8中的方法引用是一种简化Lambda表达式的方式,它允许我们直接引用已存在的 Java 类或对象的方法,而不需要通过 Lambda 表达式再去定义一个新的函数式接口实现。可以用两个冒号(::)来表示方法引用,其中左边是对象或类名,右边是方法名,语法如下:

  • 静态方法引用

    ClassName::staticMethodName

  • 实例方法引用

    objectReference::instanceMethodName

  • 对象超类方法引用

    SuperClassName::instanceMethodName

  • 构造函数引用

    ClassName::new

7.Optional 容器类型

Optional 类型是一种容器类型,表示一个值可能为空的情况,可以帮助我们避免 NullPointerException 异常,同时也可以让代码更加简洁明了。Optional 接口定义了一组方法,用于检测是否有值,获取值,处理值等操作。以下是一些常用方法:

of() 方法:创建一个包含指定非空值的 Optional 对象。

Optional<String> optional = Optional.of("Hello");

ofNullable() 方法:创建一个可能包含 null 值的 Optional 对象。

Optional<String> optional = Optional.ofNullable(null);

isPresent()方法:判断 Optional 中是否存在值。返回ture表示存在值 返回false表示为null

Optional<String> optional = Optional.ofNullable("Hello");
if (optional.isPresent()) {
    System.out.println("Value is " + optional.get());
}

get() 方法:如果 Optional 的值存在则返回该值,否则抛出 NoSuchElementException 异常。

Optional<String> optional = Optional.ofNullable("Hello");
String value = optional.get();

orElse() 方法:如果值存在则返回该值,否则返回参数中指定的默认值。

String defaultValue = "World";
Optional<String> optional = Optional.empty();
String value = optional.orElse(defaultValue); // value = "World"

orElseGet() 方法:如果值存在则返回该值,否则运行参数中的 Supplier 函数,并返回该函数的结果。

Supplier<String> supplier = () -> "World";
Optional<String> optional = Optional.empty();
String value = optional.orElseGet(supplier); // value = "World"

map() 方法:如果值存在则使用该值执行提供的 Function 函数,并返回包含其返回值的 Optional 对象;否则返回一个空的 Optional 对象。

Function<String, String> function = (s) -> s + " World!";
Optional<String> optional = Optional.of("Hello");
Optional<String> result = optional.map(function); // result = Optional[Hello World!]

filter() 方法:如果值存在并且满足指定的 Predicate 条件,则返回包含该值的 Optional 对象;否则返回一个空的 Optional 对象。

Predicate<String> predicate = (s) -> s.contains("l");
Optional<String> optional = Optional.of("Hello");
Optional<String> result = optional.filter(predicate); // result = Optional[Hello]
8.Parallel Streams

Java 8 中引入了并行流(Parallel Streams)的功能,能够有效地利用多核处理器处理大量数据集合。

并行流与普通流 API 几乎相同,但它会将操作分解成几个小块,在不同的 CPU 上进行处理,并最后将结果合并起来。因此,并行流可以显著提高大型数据集合的处理速度。下面是一个简单的例子。

假设我们需要对一个包含 1000 万个随机数的数组进行排序,然后筛选出其中所有能被 3 整除的元素。这个任务很复杂,因此可以考虑采用并行流来优化代码性能:

//创建一个包含1000万个随机数的数组
int[] arr = new int[10000000];
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
    arr[i] = random.nextInt(100);
}// 串行方式
long start1 = System.currentTimeMillis();
List<Integer> list1 = Arrays.stream(arr).sorted().filter(n -> n % 3 == 0).boxed().collect(Collectors.toList());
long end1 = System.currentTimeMillis();
System.out.println("Serial time: " + (end1 - start1) + "ms");// 并行方式
long start2 = System.currentTimeMillis();
List<Integer> list2 = Arrays.stream(arr).parallel().sorted().filter(n -> n % 3 == 0).boxed().collect(Collectors.toList());
long end2 = System.currentTimeMillis();
System.out.println("Parallel time: " + (end2 - start2) + "ms");

以上代码通过随机数生成器创建了一个包含 1000 万个随机数的数组,并参照条件对数组进行了排序和筛选过滤。

其中通过串行流(Stream)和并行流(Parallel Stream)两种方式,分别实现了对数据的操作,并在控制台输出操作所消耗的时间。

可以看出,在数据规模比较大时,使用并行流会更能发挥多核 CPU 的优势,减少整个操作过程的耗时。

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

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

相关文章

云平台 stm32连接阿里云2023最新版本保姆级别教学只看这一篇就够了~

注册账号 阿里云平台点击直达 点击控制台 鼠标悬浮会出现下拉栏 点击物联网 再点击物联网平台 点击公共实例 新用户需要开通 开通需要五分钟的时间 点击创建产品 蓝色显眼字体 参数设置 仔细比对下图 点击查看产品详情 蓝色显眼字体 点击功能定义 点击编辑草图 实际上就是定义…

如何通过Android平台的API实现5G网络的支持 安卓系统版本和5g网络相关【一】

前面分享了两篇5G基带相关的移植修改博文。 安卓高通机型的基带移植 修改 编译的相关 增加信号 支持5G等【一】 安卓高通机型的基带移植 修改 编译的相关 增加信号 支持5G等【二】 今天的帖子聊聊安卓版本与5G网络与机型和修改之间相关的话题。众所周知&#xff0c;目前的机型…

如何获取签章定位信息

在合同系统中&#xff0c;经常需要在合同文档的特定位置放置签名/印章图片。在合同拟稿过程中&#xff0c;放置签名/印章图片只是为了获取一个精确的定位信息&#xff0c;在合同定稿阶段才根据拟稿阶段得到的位置信息&#xff0c;去插入真正的签名/印章。那么如何在合同系统中高…

基于OpenMV的疲劳驾驶检测系统的设计

一、前言 借助平台将毕业设计记录下来&#xff0c;方便以后查看以及与各位大佬朋友们交流学习。如有问题可以私信哦。 本文主要从两个方面介绍毕业设计&#xff1a;硬件&#xff0c;软件&#xff08;算法&#xff09;。以及对最后的实验结果进行分析。感兴趣的朋友们可以评论区…

创新案例|专注在线 协作平台 设计产品中国首家PLG独角兽企业蓝湖如何实现98%的头部企业渗透率

蓝湖起步于2015年&#xff0c;是一款服务于产品经理、设计师、工程师的产品设计研发在线协作工具&#xff0c; 2021年10月&#xff0c;蓝湖宣布完成C轮融资&#xff0c;融资额高达10亿人民币&#xff0c;称为中国2B市场中首家采用PLG发展的独角兽企业&#xff0c;并实现了从100…

conda虚拟环境列表错误module ‘attr‘ has no attribute ‘s‘的解决方法

列出虚拟环境列表命令&#xff1a;conda info -e 或者conda env listconda info -e 这个可以正常显示&#xff0c;conda env list却报错了&#xff0c;以前是没有问题的&#xff0c;因为这个命令我更习惯使用&#xff0c;所以这个小问题必须解决掉&#xff0c;或许其他读者可能…

undetected_chromedriver解决网页被检测

一、问题分析 selenium打开浏览器模仿人工操作是诸多爬虫工作者最万能的网页数据获取方式&#xff0c;但是在做自动化爬虫时&#xff0c;经常被检测到是selenium驱动。比如前段时间selenium打开维普高级搜索时得到的页面是空白页&#xff0c;懂车帝对selenium反爬也很厉害。 二…

【React】setState原理,SCU,不可变对象,Ref,受控组件,高阶组件,封装轮播图组件

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录 setState原理setState异步更新 SCU不可变对象RefRef获取DOMRef获取组件 非受控组件受控组件高阶…

word目录怎么自动生成,3个步骤轻松搞定!

案例&#xff1a;我在做策划案的时候&#xff0c;需要制作目录。我觉得自己手动制作目录很困难&#xff0c;通过word的可以自动生成目录&#xff0c;但是我不知道具体的操作方法。有没有小伙伴可以分享一下&#xff1f; 在制作任务书、书写论文的时候&#xff0c;经常需要添加…

vue+java+springboot企业办公人事oa办公管理系统2142g

本企业OA管理系统有管理员和用户。管理员功能有个人中心&#xff0c;用户管理&#xff0c;公告信息管理&#xff0c;客户关系管理&#xff0c;通讯录管理&#xff0c;日程安排管理&#xff0c;车辆信息管理&#xff0c;文件信息管理&#xff0c;工作日志管理&#xff0c;上班考…

0基础学习VR全景平台篇第42篇:编辑器底部菜单-分组管理

大家好&#xff0c;欢迎观看蛙色VR官方系列——后台使用课程&#xff01; 本期为大家带来蛙色VR平台&#xff0c;底部菜单—分组管理功能操作。 功能位置示意 一、本功能将用在哪里&#xff1f; 分组管理&#xff0c;指观看者可点击不同分组&#xff0c;查看不同类型全景内容…

learn C++ NO.9——string(2)

引言&#xff1a; 现在是北京时间的2023年6月15日早上的10点14分。时间过得飞快&#xff0c;现在已经大一的最后一个星期了。明天也是大一最后一次课&#xff0c;线下的实训课。线下实训内容为c语言二级的内容&#xff0c;对我来说跟学校的课效率太低下了&#xff0c;我还是比…

初识网络之再看udp协议

目录 一、端口号 1. 五元组 2. 端口号范围划分 3. 一些知名端口号 4. 进程与端口号 5. 两个常用网络工具 5.1 netstat 5.2 pidof 二、UDP协议 1. udp协议格式 2. udp报文解包 3. udp报文分用 4. udp的特点 5. 缓冲区 5.1 tcp缓冲区 5.2 udp缓冲区 6. 一些常见…

函数重载异常的常见原因

函数重载异常的常见原因 使用重载函数时&#xff0c;如果数据类型不匹配&#xff0c;C尝试使用类型转换与形参进行匹配&#xff0c;如果转换后有多个函数能匹配上&#xff0c;编译将报错。引用可以作为函数重载的条件&#xff0c;但是&#xff0c;调用重载函数的时候&#xff0…

Linux:端口

端口是设备与外界进行通讯的出入口&#xff0c;端口可以分为物理端口和虚拟端口 物理端口&#xff1a;又叫接口&#xff0c;是可见的端口&#xff0c;比如HDMI端口、USB接口虚拟端口&#xff1a;是指计算机内部的端口&#xff0c;用来操作系统和外部进行交互使用 通过IP地址只能…

6.python高频函数-处理缺失值isnull()、fillna()、dropna()

前言 如何判断pandas.DataFrame、Series是否包含缺失值NaN以及如何处理缺失值NaN。 Part.1 isnull() 函数 使用 isnull()、isna() 确定每个元素的缺失值 如果值为 NaN&#xff0c;则值为 True&#xff0c;如果不是&#xff0c;则值为 False。 读取数据集 panel_data pd.r…

从C语言到C++_19(容器适配器+stack和queue模拟实现+优先级队列priority_queue)

目录 1. 容器适配器 1.1 什么是适配器 1.2 STL标准库中stack和queue的底层结构 2. stack和queue的模拟实现 2.1 stack模拟实现 2.2 queue的模拟实现 3. deque的介绍(了解) 3.1 deque的实现原理 3.2 deque的缺陷和使用场景 4. 优先级队列 priority_queue 4.1 priorit…

编码规范、Git分支整理

代码命名规范 包命名规范 采用反域名命名规则&#xff0c;全部使用小写字母。一级包名为com&#xff0c;二级包名kl&#xff08;为公司名称&#xff0c;可以简写&#xff09;&#xff0c;三级包名pos&#xff08;根据应用进行命名&#xff09;&#xff0c;四级包名activity或…

芳禾数据CTO李明:数据分类分级与治理驱动下的应用革命丨数据猿专访

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 我们进入数字化时代&#xff0c;数据已经变得比任何时候都更加关键。每天&#xff0c;我们都在生成、处理和存储海量的数据&#xff0c;这些数据在企业决策、市场研究、产品开发等方面扮演着重要的角色。然而&#xff0c;数…

Qt编写精美输入法(历时十年迭代/可换肤/支持Qt4/5/6/win/linux/mac/嵌入式等)

一、前言 大概是从2012年就开始研究用Qt写输入法&#xff0c;因为项目需要&#xff0c;嵌入式板子上&#xff0c;没有对应的输入法&#xff0c;当初使用过很多NVR&#xff0c;里面也是鼠标按下弹出输入法面板进行输入&#xff0c;可以切换数字和字母及中文&#xff0c;于是借鉴…