Java8新特性全面

news2024/11/15 21:21:57

文章目录

  • 一、函数式接口
  • 二、Java内置函数式接口
  • 三、接口内允许添加默认实现的方法
  • 四、Lambda表达式
  • 五、方法引用
  • 六、Stream API
  • 七、Stream API示例
    • 1. Filter过滤
    • 2. Sorted排序
    • 3. Map转换
    • 4. Match匹配
    • 5. Count计数
    • 6. Reduce
    • 7. Parallel-Streams并行流
    • 8. Map集合
  • 八、新时间日期接口API
  • 九、Annotations注解
    • 回顾注解
    • Java8注解
      • 类型注解
      • 重复注解

参考文章:放大招了,肝了一篇8万字的Java8新特性总结,赶快收藏

一、函数式接口

函数式接口:只包含一个抽象方法的接口,称为函数式接口,并且可以使用lambda表达式来创建该接口的对象,可以在任意函数式接口上使用@FunctionalInterface注解,来检测它是否是符合函数式接口。同时javac也会包含一条声明,说明这个接口是否符合函数式接口。

1. 自定义函数式接口

//自定义函数式接口
@FunctionalInterface
public interface MyNuber{
	public double getValue();
}

2. 泛型函数式接口

//函数式接口中使用泛型
@FunctionalInterface
public interface MyFunc<T>{
	public T getValue(T t);
}

二、Java内置函数式接口

在这里插入图片描述

三、接口内允许添加默认实现的方法

在下面这个接口中,我们除了定义了一个抽象方法 study,还定义了一个带有默认实现的方法 play。 我们在实现这个接口时,可以只需要实现 study方法,默认方法 play可以直接调用即可,也就是说我们可以不必强制实现 sqrt 方法。

// 定义一个公式接口
interface school{
    // 学习
    void study();

    // 做游戏
    default string play(String name) {
        return "我和"+ name + "一起做游戏";
    }
}

注:通过 default 关键字这个新特性,可以非常方便地对之前的接口做拓展,而此接口的实现类不必做任何改动,减少了耦合性。

School school = new School() {
    @Override
    public void study() {
        system.out.println("学习中");
    }
};

四、Lambda表达式

函数式接口(Functional Interface)就是只包含一个抽象方法的声明。针对该接口类型的所有 Lambda 表达式都会与这个抽象方法匹配。

(参数列表) -> { 方法体 }

  1. 参数列表的数据类型可以省略
  2. 参数列表只有一个参数,可以把()去掉
  3. 如果方法体只有一条语句,可以把 { } 和 return 去掉
  1. 无参、无返回值
public void test1(){
	Runnable r1 = new Runnable(){
		@Override
		public void run(){
			System.out.println("我爱北京天安门");
		}
	};

	Runnable r2 = ()->{
		System.out.println("我爱北京天安门");
	};
}
  1. 需要一个参数,但是没有返回值;
@Test
public void test2(){
    Consumer<String> con1 = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s + 1);
        }
    };

    Consumer<String> con2 = (String s)->{
    	System.out.println(s + 2);
	}
	
	//数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
    Consumer<String> con3 = (s)->{
    	System.out.println(s + 3);
	}
}
  1. Lambda 若只需要一个参数时,参数的小括号可以省略
@Test
public void test3(){
    Consumer<String> con1 = (s) -> {
        System.out.println(s);
    };

    Consumer<String> con2 = s -> {
        System.out.println(s);
    };
}
  1. Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
@Test
public void test4(){
    Comparator<Integer> com1 = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
                System.out.println(o1 + o2);
            System.out.println(o1);
        }
    };

    Comparator<Integer> com2 = (o1,o2) -> {
           System.out.println(o1 + o2);
        return o1.compareTo(o2);
    };
}
  1. 当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略
@Test
public void test5(){
    Comparator<Integer> com1 = (o1,o2) -> {
        return o1.compareTo(o2);
    };

    Comparator<Integer> com2 =  (o1,o2) -> o1.compareTo(o2);
}

五、方法引用

有下列三种情况

  • 对象 :: 实例方法
  • 类 :: 实例方法
  • 类 :: 静态方法
  1. 方法引用
package com.chen.test.JAVA8Features;public class MethodRefDemo {
    public static void main(String[] args) {
        FunctionGeneric<String> strName = s -> System.out.println(s);
        strName.fun("Lambda表达式没有使用方法引用");
        
        //方法引用
        FunctionGeneric<String> strName2 = System.out::println;
        strName2.fun("使用方法引用");
    }
}
  1. 构造器引用
package com.chen.test.JAVA8Features;import java.util.function.Function;public class MethodRefDemo {
    public static void main(String[] args) {
        //构造器引用
        Function<String, Integer> fun1 = (num) -> new Integer(num);
        Function<String, Integer> fun2 = Integer::new;//数组引用
        Function<Integer,Integer[]> fun3 = (num) ->new Integer[num];
        Function<Integer,Integer[]> fun4 = Integer[]::new;
    }
}

六、Stream API

StreamAPI帮助我们更好地对数据进行集合操作,它本质就是对数据的操作进行流水线式处理,也可以理解为一个更加高级的迭代器,主要作用是遍历其中每一个元素。简而言之,StreamAP提供了一种高效且易于使用的处理数据方式。

Stream操作的三个步骤

  1. 创建流
//第一种:通过集合:对于Collection接口(List 、Set、Queue等)直接调用Stream()方法可以获取Stream
        List<String> list = new ArrayList<>();
        Stream<String> stringStream = list.stream(); //返回一个顺序流
        Stream<String> parallelStream = list.parallelStream(); //返回一个并行流(可多线程)

//第二种:通过数组
        Stream<String> stream1 = Arrays.stream(new String[]{"CBB", "YJJ", "CB", "CJJ"});//第三种:Stream.of()静态方法直接手动生成一个Stream
        Stream<String> stream = Stream.of("A", "B", "C", "D");
  1. 中间操作:一个流可以后面跟随着0个或者多个中间操作,其目的是打开流,做出某种程度的数据过滤、去重、排序、映射、跳过等。然后返回一个新的流,交给下一个使用,仅仅是调用这个方法,没有真正开始遍历。

map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

3、终止操作:一个终止操作,执行中间操作连,产生结果

forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

七、Stream API示例

首先,我们创建一个List集合

//首先我们创建一个List集合
List<String> stringCollection = new ArrayList<>();
stringCollection.add("ddd2");
stringCollection.add("aaa2");
stringCollection.add("bbb1");
stringCollection.add("aaa1");
stringCollection.add("bbb3");
stringCollection.add("ccc");
stringCollection.add("bbb2");
stringCollection.add("ddd1");

1. Filter过滤

stringCollection
    .stream()
    .filter((s) -> s.startsWith("a"))
    .forEach(System.out::println);

// "aaa2", "aaa1"

2. Sorted排序

stringCollection
    .stream()
    .sorted()
    .filter((s) -> s.startsWith("a"))
    .forEach(System.out::println);

// "aaa1", "aaa2"

3. Map转换

stringCollection
    .stream()
    .map(String::toUpperCase)
    .sorted((a, b) -> b.compareTo(a))
    .forEach(System.out::println);

// "DDD2", "DDD1", "CCC", "BBB3", "BBB2", "AAA2", "AAA1"

4. Match匹配

// 验证 list 中 string 是否有以 a 开头的, 匹配到第一个,即返回 true
boolean anyStartsWithA =
    stringCollection
        .stream()
        .anyMatch((s) -> s.startsWith("a"));

System.out.println(anyStartsWithA);      // true
// 验证 list 中 string 是否都是以 a 开头的
boolean allStartsWithA =
    stringCollection
        .stream()
        .allMatch((s) -> s.startsWith("a"));

System.out.println(allStartsWithA);      // false
// 验证 list 中 string 是否都不是以 z 开头的,
boolean noneStartsWithZ =
    stringCollection
        .stream()
        .noneMatch((s) -> s.startsWith("z"));

System.out.println(noneStartsWithZ);      // true

5. Count计数

// 先对 list 中字符串开头为 b 进行过滤,让后统计数量
long startsWithB =
    stringCollection
        .stream()
        .filter((s) -> s.startsWith("b"))
        .count();

System.out.println(startsWithB);    //

6. Reduce

Optional<String> reduced =
    stringCollection
        .stream()
        .sorted()
        .reduce((s1, s2) -> s1 + "#" + s2);

reduced.ifPresent(System.out::println);
// "aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2"

7. Parallel-Streams并行流

stream 流是支持顺序和并行的。顺序流操作是单线程操作,而并行流是通过多线程来处理的,能够充分利用物理机 多核 CPU 的优势,同时处理速度更快。

首先,我们创建一个包含 1000000 UUID list 集合

int max = 1000000;
List<String> values = new ArrayList<>(max);
for (int i = 0; i < max; i++) {
    UUID uuid = UUID.randomUUID();
    values.add(uuid.toString());
}

分别通过顺序流和并行流,对这个 list 进行排序,测算耗时:
顺序流:

// 纳秒:获取当前时间1
long t0 = System.nanoTime();

//获取串行流输出
long count = values.stream().sorted().count();
System.out.println(count);

//纳秒:获取当前时间2
long t1 = System.nanoTime();

// 纳秒转微秒
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("顺序流排序耗时: %d ms", millis));

// 顺序流排序耗时: 899 ms

并行流

// 纳秒:获取当前时间1
long t0 = System.nanoTime();

//并行流输出
long count = values.parallelStream().sorted().count();
System.out.println(count);

//纳秒:获取当前时间2
long t1 = System.nanoTime();

// 纳秒转微秒
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("并行流排序耗时: %d ms", millis));

// 并行流排序耗时: 472 ms

同样的逻辑处理,通过并行流,我们的性能提升了近 50%。完成这一切,我们需要做的仅仅是将 stream 改成了 parallelStream。

8. Map集合

前面已经提到过 Map 是不支持 Stream 流的,因为 Map 接口并没有像 Collection 接口那样,定义了 stream() 方法。

注:我们可以对其 key, values, entry 使用 流操作,如 map.keySet().stream(), map.values().stream() 和 map.entrySet().stream().

八、新时间日期接口API

参考文章:Java自定义注解

九、Annotations注解

回顾注解

  1. 四个常用的元注解:负责注解其他注解
  • @Target:用于描述注解的使用范围:接口、类、枚举等等
  • @Retention:表示在”source、class、runtime“哪个阶段,注解依然存在
  • @Documented:说明该注解将被包含在javadoc中
  • @Inherited:说明子类可以继承父类中的该注解
//使用自定义注解
//通过四个元注解自定义注解
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface  MyAnnotation{
    
}

@MyAnnotation
public class Test01{
    public void test(){
        System.out.println("hello");
    }
}

Java8注解

对于注解(也被称做元数据),Java 8 主要有两点改进:类型注解和重复注解。

类型注解

类型注解被用来支持在Java的程序中做强类型检查。配合第三方插件工具Checker Framework,可以在编译的时候检测出runtime error,以提高代码质量。这就是类型注解的作用。

import checkers.nullness.quals.*;
public class TestDemo{
    void sample() {
        @NonNull Object my = new Object();	//通过,不报错
    }
}

重复注解

允许在同一声明类型(类,属性,或方法)上多次使用同一个注解。

Java8以前的版本使用注解有一个限制是相同的注解在同一位置只能使用一次,不能使用多次。

Java 8 引入了重复注解机制,这样相同的注解可以在同一地方使用多次。重复注解机制本身必须用 @Repeatable 注解。

实际上,重复注解不是一个语言上的改变,只是编译器层面的改动,技术层面仍然是一样的。

1) 自定义一个包装类Hints注解用来放置一组具体的Hint注解

@interface MyHints {
    Hint[] value();
}
 
@Repeatable(MyHints.class)
@interface Hint {
    String value();
}

使用包装类当容器来存多个注解(旧版本方法)

@MyHints({@Hint("hint1"), @Hint("hint2")})
class Person {}

使用多重注解(新方法)

@Hint("hint1")
@Hint("hint2")
class Person {}

  1. 完整类测试
public class RepeatingAnnotations {
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Filters {
        Filter[] value();
    }
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Repeatable(Filters.class)
    public @interface Filter {
        String value();
    }
    @Filter("filter1")
    @Filter("filter2")
    public interface Filterable {
    }
    public static void main(String[] args) {
        for (Filter filter : Filterable.class.getAnnotationsByType(Filter.class)) {
            System.out.println(filter.value());
        }
    }
}

输出结果:
filter1
filter2

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

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

相关文章

天津+发展得到的权重

添加评分添加评分的依据高德地图找到如图数据&#xff0c;容积率体现楼层高度近似反映人口密度&#xff0c;繁华程度近似等价霓虹灯照明时长住房容积率具体是指在城市规划区的某一宗地内&#xff0c;房屋的总建筑面积与宗地面积的比值&#xff0c;分为实际容积率和规划容积率两…

链表学习基础

链表 通过指针串联在一起的线性结构&#xff0c;每个节点由数据域和指针域两部分组成。链表节点在内存中的存储通常不是连续的&#xff0c;各节点通过指针连接在一起&#xff0c;其内存分布大致如下图所示。 定义 单链表 struct ListNode {// DATATYPE 可以是任意存放数据的…

HTTP基础知识

关键字&#xff1a;一问一答用于和服务器交互什么是HTTPHTTP是个应用层协议&#xff0c;是HTTP客户端和HTTP服务器之间的交互数据格式。所以这里有个实例&#xff1a;在浏览网页的时候&#xff0c;浏览器会向服务器发送一个HTTP请求&#xff0c;告诉服务器我想访问什么..然后服…

图论学习03

图神经网络模型介绍 将图神经网络分为基于谱域上的模型和基于空域上的模型&#xff0c;并按照发展顺序详解每个类别中的重要模型。 基于谱域的图神经网络 谱域上的图卷积在图学习迈向深度学习的发展历程上起到了关键性的作用。三个具有代表性的谱域图神经网络 谱图卷积网络切…

c++中超级详细的一些知识,新手快来

目录 2.文章内容简介 3.理解虚函数表 3.1.多态与虚表 3.2.使用指针访问虚表 4.对象模型概述 4.1.简单对象模型 4.2.表格驱动模型 4.3.非继承下的C对象模型 5.继承下的C对象模型 5.1.单继承 5.2.多继承 5.2.1一般的多重继承&#xff08;非菱形继承&#xff09; 5.2…

奥地利、爱沙尼亚重要机构或正成为俄黑客目标

近日&#xff0c;网络安全公司Sekoia有一项新发现&#xff1a;由俄罗斯政府支持的黑客组织“图拉”&#xff08;Turla&#xff09;正在对奥地利经济商会、北约平台、波罗的海国防学院&#xff08;Baltic Defense College&#xff09;发动一系列攻击。这是Sekoia公司基于Google …

One Fuzzing Strategy to Rule Them All

One Fuzzing Strategy to Rule Them All 文章目录One Fuzzing Strategy to Rule Them All相关链接概述背景实验测试RQ1&#xff1a;RQ2相关工作总结最后相关链接 One Fuzzing Strategy to Rule Them All 参考链接 概述 在本文中作者提出了对变异策略havoc的研究&#xff0c…

linux异步IO编程实例分析

在Direct IO模式下&#xff0c;异步是非常有必要的&#xff08;因为绕过了pagecache&#xff0c;直接和磁盘交互&#xff09;。linux Native AIO正是基于这种场景设计的&#xff0c;具体的介绍见&#xff1a;KernelAsynchronousI/O (AIO)SupportforLinux。下面我们就来分析一下…

大数值金额大写转换(C语言)

关于大数值金额大写转换&#xff0c;在财务管理的应用方面没什么意义。一般来说&#xff0c;千亿级&#xff0c;万亿级的数值就够了。因为在国家级层面是以亿为单位的&#xff0c;也就表达为千万亿&#xff0c;万万亿。在企业层面数值金额转换设置到千亿、万亿就行了。大的集团…

RabbitMQ 入门到应用 ( 四 ) 与SpringBoot整合

5.与SpringBoot整合 5.1.SpringBoot项目中配置环境 5.1.1.pom.xml配置依赖 在 pom.xml 配置文件中声明依赖, 通过Maven导入 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> &l…

天津数据得出的权重

目标层&#xff1a;评价光污染准则层为四个大类&#xff1a;道路、商业、住宅、绿化方案层为25个小类指标但每个大类只和自己下面的几个小类指标相关&#xff0c;不是图示的下面两层全有关联或许考虑把25个小指标提取公共部分&#xff0c;比如路灯亮度、高度、和外墙的距离、光…

RocketMQ 2m-2s-async搭建

本文档是RocketMQ4.8两主两从异步复制的搭建过程&#xff08;也可单机部署&#xff0c;更简单一点&#xff09;,包括监控台界面. 写在前面&#xff1a;本文档适用于4.8版本&#xff0c;其它版本的坑没有踩过不清楚。我是用VMware启了两台虚拟机&#xff0c;环境&#xff1a;Ce…

10 OpenCV图像识别之人脸追踪

文章目录1 级联分类器2 人脸跟踪2.1 相关方法2.2 代码示例CV2中内置了人脸识别等常用的算法&#xff0c;这类算法是通过级联分类器实现的。 1 级联分类器 级联分类器的核心思想是使用多个分类器级联&#xff0c;每个分类器负责检测不同的特征&#xff0c;逐步排除不可能是目标…

Prometheus离线tar.gz包安装

Prometheus离线tar.gz包安装实验环境一、部署前操作二、Master2.1下载2.2解压2.3更改服务目录名称2.4创建系统服务启动文件2.5配置修改2.6启动并设置开机自启2.7访问2.8添加node节点2.8.1 添加方法2.8.2修改Prometheus配置&#xff08;Master&#xff09;实验环境节点ipcpu内存…

数据结构:归并排序和堆排序

归并排序 归并排序(merge sort)是利用“归并”操作的一种排序方法。从有序表的讨论中得知,将两个有序表“归并”为一个有序表,无论是顺序表还是链表,归并操作都可以在线性时间复杂度内实现。归并排序的基本操作是将两个位置相邻的有序记录子序列R[i…m]R[m1…n]归并为一个有序…

已解决zipfile.BadZipFile: File is not a zip file

已解决Python openpyxl 读取Excel文件&#xff0c;抛出异常zipfile.BadZipFile: File is not a zip file的正确解决&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 文章目录报错问题报错翻译报错原因解决方法联系博主免费帮忙解决报错报错问题 一个小伙伴遇到问题跑…

python基于django+vue微信小程序的校园二手闲置物品交易

在大学校园里,存在着很多的二手商品,但是由于信息资源的不流通以及传统二手商品信息交流方式的笨拙,导致了很多仍然具有一定价值或者具有非常价值的二手商品的囤积,乃至被当作废弃物处理。现在通过微信小程序的校园二手交易平台,可以方便快捷的发布和交流任何二手商品的信息,并…

【CS224W】(task2)传统图机器学习和特征工程

note 和CS224W课程对应&#xff0c;将图的基本表示写在task1笔记中了&#xff1b;传统图特征工程&#xff1a;将节点、边、图转为d维emb&#xff0c;将emb送入ML模型训练Traditional ML Pipeline Hand-crafted feature ML model Hand-crafted features for graph data Node-l…

被滥用的Slack服务:APT29针对意大利的攻击活动分析

背景 APT29&#xff0c;又名CozyBear, Nobelium, TheDukes&#xff0c;奇安信内部编号APT-Q-77&#xff0c;被认为是与东欧某国政府有关的APT组织。该组织攻击活动可追溯至2008年&#xff0c;主要攻击目标包括西方政府组织机构、智囊团。APT29曾多次实施大规模鱼叉攻击&#x…

linux高级命令之进程的注意点

进程的注意点学习目标能够说出进程的注意点1. 进程的注意点介绍进程之间不共享全局变量主进程会等待所有的子进程执行结束再结束2. 进程之间不共享全局变量import multiprocessing import time# 定义全局变量 g_list list()# 添加数据的任务defadd_data():for i in range(5):g…