赞
踩
目录
允许把函数作为一个方法的参数,可替换匿名内部类。

- // 无参数无返回值:
- () -> System.out.println("Hello World")
-
- // 有一个参数无返回值:
- (x) -> System.out.println(x)
-
- // 有一个参数无返回值,可省略参数小括号:
- x -> System.out.println(x)
-
- // 有多个参数,有返回值,有多条Lambda语句:
- (x,y) -> {System.out.println("xxx"); return "sdf";}
-
- // 有多个参数,有返回值,只有一条Lambda语句:
- (x, y) -> xxx
对一个集合中的一系列元素进行聚合操作。
Stream 的一系列操作必须要使用终止操作,否者整个数据流是不会流动起来的,即处理操作不会执行。
Stream不会存储元素;
Stream不会改变源对象,会返回一个持有结果的Stream;
Stream操作是延时执行的,会等到需要结果的时候才会去真正执行。
中间操作符

终止操作符

示例
- List<String> list = Arrays.asList(new String[]{"15","32","25","64","32"});
- list.stream().distinct().forEach(item -> System.out.println(item));
主要是为了解决空指针异常NullPointException问题
构造方法
- Optional.of(T)
-
- 该方式的入参不能为null,否则会有NPE,在确定入参不为空时使用该方式。
-
- Optional.ofNullable(T)
-
- 该方式的入参可以为null,当入参不确定为非null时使用。
-
- Optional.empty()
-
- 这种方式是返回一个空Optional,等效Optional.ofNullable(null)
常用方法
- ifPresent() <==> obj != null
- 当Optional实例的值非空时返回true,否则返回false;
-
- orElseGet()
- 当Optional包含非空值时返回该值,否则通过接收的function生成一个默认的;
-
- map()
- 转换当前Optional的值,并返回一个新的Optional实例;
-
- orElse()
- 与orElseGet方法相似,不同的是orElse()直接返回传入的默认值。
-
- orElseThrow()
- value值为null时,直接抛出一个异常
示例
1.4、接口默认方法接口允许有实现方法,只需要在方法名前新增default关键字即可。
作用
为接口添加新方法,同时保证不影响已有的实现。
解决default方法冲突的三步骤
示例(default方法冲突)
多重继承中,如果出现了同名的默认方法



示例1:若继承的两个接口相互独立且存在相同的默认方法,则需要重写default方法,并制定继承哪一个接口的default方法。

示例2:若继承的两个接口存在相同的默认方法且为继承关系,则调用的是子类接口的default方法。

旧版时间API
新版时间API
主要有LocalDate、LocalTime和LocalDateTime三个日期类,实例为不可变对象,线程安全。JDK8新增的日期及时间位于java.time包下。
部分API举例介绍
- // 获取当前日期
- LocalDate now = LocalDate.now();
-
- // 指定日期 LocalDate.of(year,month,day)
- LocalDate date = LocalDate.of(2008, 8, 8);
-
- // 获取当前时间
- LocalTime now = LocalTime.now();
-
- // 指定日期 LocalTime.of(hour,minute,second)
- LocalTime date = LocalTime.of(13, 26, 39);
-
- // 获取当前日期时间
- LocalDateTime now = LocalDateTime.now();
-
- // 指定日期时间 LocalDateTime.of(year,month,day,hour,minute,second)
- LocalDateTime date = LocalDateTime.of(2018, 7, 23, 18, 59, 31);
-
- // 修改年[修改时间]
- System.out.println("修改年后:" + now.withYear(9102));
-
- // 增加年(减使用 minusYear()方法)
- System.out.println("+2年后:" + now.plusYears(2));

Base64只是一种编解码算法,而非加密算法,一般对重要信息做加密不使用Base64。
- import java.io.UnsupportedEncodingException;
- import java.util.Base64;
- import java.util.Base64.Decoder;
- import java.util.Base64.Encoder;
-
- /**
- * jdk8提供的Base64编解码效率远大于sun.misc和 Apache Commons Codec的效率
- */
- public class Base64Test {
-
- public static void main(String[] args) {
- String str = "这是一次Base64编解码测试";
-
- Encoder encoder = Base64.getEncoder(); // 编码对象
- Decoder decoder = Base64.getDecoder(); // 解码对象
- try {
- // 1.编码
- String encoderStr = encoder.encodeToString(str.getBytes("UTF-8"));
- System.out.println(encoderStr);//6L+Z5piv5LiA5qyhQmFzZTY057yW6Kej56CB5rWL6K+V
-
- // 2.解码
- byte[] decode = decoder.decode(encoderStr);
- System.out.println(new String(decode, "UTF-8")); // 这是一次Base64编解码测试
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
-
- }

常与Lambda表达式一起使用。
如果Lambda表达式所要实现的功能,可以用其他方法替代,那么则可以使用方法引用。
引用方式
- 1、instanceName::methodName 对象::方法名
-
- 2、ClassName::staticMethodName 类名::静态方法
-
- 3、ClassName::MethodName 类名::普通方法
-
- 4、ClassName::new 类名::new 调用的构造器
-
- 5、TypeName[]::new String[]::new 调用数组构造器
举例说明
- List<LocalDate> dates = new ArrayList<>();
- dates.add(LocalDate.now());
- dates.add(LocalDate.of(2019, 11, 12));
- dates.add(LocalDate.of(2020, 5, 6));
-
- // 获取年份集合
- List<Integer> years = dates.stream().map(LocalDate::getYear).collect(Collectors.toList());
- System.out.println(years);
- // Stream串行
- long count = IntStream.range(0, 100000).filter(this::isPrime).count();
- System.out.println(count);
-
- // Stream并行
- long count1 = IntStream.range(0, 100000).parallel().filter(this::isPrime).count();
- System.out.println(count1);
-
-
- // 获取一个并行流
- List<JSONObject> objects = Lists.newArrayList();
- Stream<JSONObject> jsonObjectStream = objects.parallelStream();
-
-
- // 并行数组
- long[] arrayOfLong = new long [20000];
-
- 。。。省略数组的初始化。。。
-
- Arrays.parallelSort( arrayOfLong );

LongAdder、CompletableFuture、StampedLock
JDK8中的接口新增了默认方法,允许在接口中定义方法体。从JDK9开始,可以在接口中添加private的私有方法和私有静态方法,不将私有方法暴露给接口的实现类调用。
在一个局部定义(方法内部)中,编译器可以自动发现类型。在编译时,编译器会检查赋值语句右侧代码,从而推断出具体类型。它查看声明的右侧,如果这是一个初始化语句,它会用那个类型取代var。
- // 简化类型,变量名尽量见名知意
- // DocumentationTool dtl = new DocumentationTool();
- var dockmentationTool = new DocumentationTool();
-
-
- // 使用数据类型标志来帮助var去推断出预期的基本数据类型(int, long, float, double)
- var intNumber = 20; // 推断为int
- var longNumber = 20L; // 推断为long
- var floatNumber = 20F; // 推断为float, 20.0
- var doubleNumber = 20D; // 推断为double, 20.0
-
在case语句中,使用箭头替换老版的冒号,可以省略break语句。
- // switch case旧方式
- public void old(int i) {
- switch(i) {
- case 1: System.out.println("one");
- break;
- case 2: System.out.println("two");
- break;
- case 3: System.out.println("three");
- break;
- default: System.out.println("default");
- }
- }
-
-
- // switch case新方式
- public void new(int i) {
- switch(i) {
- case 1 -> System.out.println("one");
- case 2 -> System.out.println("two");
- case 3 -> System.out.println("three");
- default -> System.out.println("default");
- }
- }

将switch作为一个表达式,可以通过switch获取一个值。
在使用冒号语法时,可以使用yield关键字从switch中返回结果,yield和break不能同时使用。
- public void test1(int i) {
- String result = switch(i) {
- case 1: yield "one";
- case 2: yield "two";
- case 3: yield "three";
- default: yield "default";
- }
- System.out.println(result);
- }
-
-
- public void test2(int i) {
- String result = switch(i) {
- case 1 -> "one";
- case 2 -> "two";
- case 3 -> "three";
- default -> "default";
- }
- System.out.println(result);
- }

- public void dumb(Object x) {
- if (x instanceof String s && s.length() > 0) {
- System.out.format("%d %s%n", s.length(), s.toUpperCase())
- }
- }
如上示例所示,如果x是String类型,就会自动用String类型创建一个新的变量s(s被称为模式变量),s在整个作用域中都可用。
但是,在某些极端情况,智能转型会产生一些奇怪的作用域行为:
- public void f1(Object o) {
- if (!(o instanceof String s)) {
- System.out.println("Not a String");
- throw new RuntimeException();
- }
- // 此处s仍在作用域中!
- System.out.println(s.toUpperCase()); //[1]
- }
-
- public void f2(Object o) {
- if (!(o instanceof String s)) {
- System.out.println("Not a String");
- }
- // 编译报错:无法找到s
- System.out.println(s.toUpperCase()); //[1]
- }

密封类/接口规定了只有指定的类/接口可以扩展和实现他们。换句话说,密封类/接口可以限制自己能派生出哪些类。
举例说明:
定义密封类(sealed ... permits ...)
sealed class Shape permits Circle, Hexagon, Rectangle {...}
sealed类的子类只能通过下面的某个修饰符来定义:
在switch中引入原本非法的case null。
- // 老版本switch case
- public void old(String s) {
- if (s == null) {
- System.out.println("null");
- return;
- }
- switch(s) {
- case "XX" -> System.out.println("XX");
- default -> System.out.println("default");
- }
- }
-
-
- // 新版本switch case
- public void new(String s) {
- switch(s) {
- case null -> System.out.println("null");
- case "XX" -> System.out.println("XX");
- default -> System.out.println("default");
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。