• Lambda 表达式
  • 方法引用
  • 函数式接口
  • 默认方法
  • Stream
  • Optional 类
  • Nashorn, JavaScript 引擎
  • 新的日期时间 API
  • Base64

 

1、lambda表达式

1.1、用法举例:

public class LambdaTest {

    public static void main(String[] args) {
        Hello h = ()->10;
        Hello1 h1 = (a,b) -> a+b;

        System.out.println(h.sayA());
        System.out.println(h1.sayB(3,4));

    }
}

interface Hello{
    int sayA();
}

interface Hello1{
    int sayB(int a,int b);
}

 

1.2、思考:

1、lambda表达式,相当于接口的实现,而该接口,必须是函数式接口,否则报错Multiple non-overriding abstract methods found in interface com.asiainfo.group.jdk8.Hello

2、lambda表达式提供了函数式编程的能力

3、像lambda表达式、方法引用的返回值一定是函数式接口,而该接口可以自己定义,也可以使用java.util.function包下面已有的类

 

1.3、语法

lambda 表达式的语法格式如下:

(parameters) -> expression 或 (parameters) ->{ statements; }

以下是lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值

 

1.4、表达式实例

// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

 

2、函数式接口

所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。

这种类型的接口也称为SAM接口,即Single Abstract Method interfaces

函数式接口可以用注解@FunctionalInterface标识

 

2.1、特点

  • 接口有且仅有一个抽象方法
  • 允许定义静态方法
  • 允许定义默认方法
  • 允许java.lang.Object中的public方法
  • 该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错

2.2、JDK中的函数式接口举例

java.lang.Runnable,

java.awt.event.ActionListener,

java.util.Comparator,

java.util.concurrent.Callable

java.util.function包下的接口,如Consumer、Predicate、Supplier等


2.3、supplier接口的理解

supplier是用来创建对象的,但是不同于传统的创建对象语法

//创建Supplier容器,声明为TestSupplier类型,此时并不会调用对象的构造方法,即不会创建对象
        Supplier<MethodReferenceTest> s = MethodReferenceTest::new;
        //调用get()方法,此时会调用对象的构造方法,即获得到真正对象
        MethodReferenceTest m1 = s.get();

        System.out.println(m1.hashCode());
        //每次get都会调用构造方法,即获取的对象不同
        MethodReferenceTest m2 = s.get();
        System.out.println(m2.hashCode());

 

3、方法引用

方法引用可以理解为Lambda表达式的另外一种表现形式

类型 语法 对应的Lambda表达式
静态方法引用 类名::staticMethod (args) -> 类名.staticMethod(args)
实例方法引用 inst::instMethod (args) -> inst.instMethod(args)
对象方法引用 类名::instMethod (inst,args) -> 类名.instMethod(args)
构建方法引用 类名::new (args) -> new 类名(args)

 

4、stream api

4.1、流的概念

流是数据渠道,用于操作数据源,所生成一种新的元素序列。集合讲的是数据,流讲的是计算,是操作

使用Stream API 对集合的数据进行操作,类似于SQL执行的数据库查询,也可以用来并行执行操作,其提供了一种高效且易于使用的处理数据方式

  • Stream自身不会存储元素
  • Stream不会改变数据源对象,相反会返回产生一个持有结果的新Stream
  • Steam操作是延迟执行的,这意味着他们会等到需要结果的时候才执行

 

流的操作步骤:

创建流 -> 中间操作 -> 终止操作

 

4.2、创建流(创建流的方式)

  • 通过Collection 系列集合提供的串行流:stream()、并行流: paralleStream()
  • 通过Arrays中的静态方法stream(T[] array) 获取数组流

  • 通过Stream类中的静态方法 of()

  • 使用Stream类的静态方法 iterate 创建无限流

  • 使用Stream类的静态方法 generate创建无限流

 

4.3、中间操作

一个中间操作链,用Stream API 对数据源数据进行操作处理

注意点

  • 若只有中间操作,则不会执行
  • 只有终止操作执行后,所有的中间操作一次执行,此时就称为延迟加载或者惰性求值

 

4.3.1、筛选与切片

filter-过滤
limit-限定元素数量
skip-跳过元素
distinct-去重

 

4.3.2、map映射

 接收一个lamda表达式作为参数,该函数会被应用到每个元素上,并将其映射到一个新的元素

 

4.3.3、排序

sorted

 

4.4、终止操作

4.4.1、查找与匹配

 

  • allMatch-检查是否匹配所有元素
  • anyMatch-检查是否至少匹配一个元素
  • noneMatch-检查是否所有元素都没有匹配到
  • findFirst-返回第一个元素
  • findAny-返回当前流中的任意一个元素
  • count-返回流中元素总个数
  • max-返回流中的最大值
  • min-返回流中的最小值


4.4.2、归约与收集

 

  • reduce-将流中元素反复结合起来,得到一个值
  • collect-将流转换为其他形式


4.4.3、Collectors类中的常用方法

 

  • counting-统计数量
  • averagingDouble-求平均值并转换成Double类型
  • summingDouble-求和并转换成Double类型
  • maxBy-根据函数条件求最大值
  • groupingBy-分组
  • partitioningBy-分区
  • summarizingDouble-计算方法总括函数
  • joining-连接字符串


4.5、stream api综合案例

List<String> list = new ArrayList<>();
        list.add("group");
        list.add("com");
        list.add("jdk8");
        list.add("java");
        list.add("util");
        list.add("");
        list.add("util");
        list.add("asiainfo");


        list.stream().filter(s -> !"".equals(s)).distinct().limit(5).sorted().map(s -> s.toUpperCase())
                .forEach(System.out::println);

 

5、optional 示例
 String s1 = "ok";
        String s2 = null;

        //ofNUllable表示可接受一个null对象,如果使用of来接受null对象则会抛出空指针异常
        Optional<String> o1 = Optional.of(s1);
        Optional<String> o2 = Optional.ofNullable(s2);

        //true表示有值,false表示为空
        System.out.println(o1.isPresent());
        System.out.println(o2.isPresent());

        //如果o2有值,则返回该值;没值,则返回hello
        String newS2 = o2.orElse("hello");

        //获取值
        System.out.println(o1.get());
        System.out.println(newS2);

 

6、List/Set/Map初始化
List<String> list = new ArrayList<String>(){{
            add("a");
            add("a");
            add("a");
        }};