Java 复习 JDK8 新特性 Lambda 和 Stream

参考自视频:https://www.bilibili.com/video/BV18b411t7Nc/

下面复习JDK8主打的两种新特性 Lambda 和 Stream

Lambda表达式

Lambda在一些动态语言中是一个匿名函数,在java中Lambda本质上是一个接口的实例化对象

格式 (o1, o2) -> Integer.compare(o1,o2)

  • 左边是形参列表(重写抽象方法的形参列表)
  • ->是Lambda操作符
  • 右边是Lambda方法体(重写抽象方法的方法体)

六种调用方式

  • Runnable runnable = () -> {System.out.println(“running”);}
  • Consumer<String> consumer = (String str) -> {System.out.println(str);}
  • Consumer<String> consumer = (str) -> {System.out.println(str);}
  • Consumer<String> consumer = str -> {System.out.println(str);}
  • Comparator<Integer> comparator = (o1, o2) -> return Integer.compare(o1, o2)
  • Comparator<Integer> comparator = (o1, o2) -> Integer.compare(o1, o2)

总结:是参数的类型可以省略,有自动推断机制,如果参数只有一个,那么括号可以省略,你把方法体应该用一对大括号来扩充,但是如果其中呢只有一条语句的话,括号可以省略,如果只有一条语句,并且是return语句,return这个关键词也可以省略。

这些都是建立在实现的接口中只有一个抽象方法(不会有歧义),这种类型的接口叫做函数式接口

函数式接口可以用FunctionalInterface注解进行修饰,类似Override注解的功能,在编译时期进行格式检查。

Lambda表达式一定依赖于函数式接口。

四大函数式接口

方法引用和构造器引用

方法引用本质上就是lambda表达式,只是一种更简便的方法,

使用要求:使用方法引用的前提是已有方法实现了接口抽象方法实现的功能,形参和返回值可以匹配上,有如下三种情况:

对象::非静态方法

Consumer <String> consumer = System.out::println;

Supplier<String> supplier = emp::getName;

类::静态方法

Comparator<Integer> comparator = Integer::compare;

Function<Double, Long> fun = Math::round;

类::实例方法(这种比较难)

BiPredicate<String, String> pre = String::equals;

Comparator<String> comparator = String::compareTo;

Function<Employee, String> func = Employee::getName;

构造器引用

Supplier<Employee> su = Employee::new;(调用空参数构造器)

Function<Integer, Employee> fun = Employee::new; (调用带一个参数integer的构造器)

BiFunction<Interger, String, Emplyee> fun2 = Employee::new;

数组引用(把数组看作一个特殊的类)

Function<Integer, String[]> fun = String[] :: new;

Stream API 真正把函数式编程风格引入到Java中,可以对集合数据进行操作,类似于SQL执行数据库查询。集合是数据在内存中,Stream是计算在CPU中

Stream不会自己存储元素,Stream也不会改变原有对象,Stream的计算是延迟的,

Stream的三个步骤,创建对象、中间操作、终止操作。

创建stream对象的方法

Collection接口中的default方法 stream 和 pararallStream

Arrays类的静态方法 stream

Stream类的静态方法 public static stream of (T…t)

创建无限流

Stream.iterate(0, t->t+2).limit(10).forEach(System.out::println) 输出前10个偶数,从0开始

Stream.generate(Math::random).limit(0).forEach(Sytem.out::println)输出10个随机数

中间操作

筛选和切片

fileter(Predicate p) 自定义筛选数据

limit(n) 截断流,取前n个数据

skip(n) 跳过前n个数据

distinct 筛选 利用流中元素的hashCode和equal方法去除重复元素。

映射

map(function fun)

Stream<String> stream = Arrays.asList("aa","bb","cc").stream();
stream.map(String::toUpperCase).forEach(System.out::println);

flatmap 扁平映射,把Stream套Stream的形式压成一层扁平的Stream

排序 sorted 自然排序和 sorted(Comparator comparator)定制排序

终止操作:

匹配和查找

allMatch anyMatch noneMatch 见面知意,参数一定是Predicate接口

findFirst、findAny、count、max(Comparator com)、min(Comparator com)

forEach(Consumer c) 内部迭代

归约 reduce(T identity, BinaryOperator)

System.out.println(Stream.iterate(1, x -> x + 1).limit(10).reduce(Integer::sum));

收集

collect(Collector c)

stream.collect(Collectors.toList()) stream.collect(Collectors.toSet())

Optional类 是用来避免空指针对程序对伤害。Optional可以理解为是一个容器或者是一个包装类,Optional有两种构造方法,一种是Optional.of(T) 一种是Optional.ofNullable()。为了避免在程序中出现空指针异常,使用orElse(备胎)方法获取Optional容器中的对象,如果是null就返回备胎,保证返回的对象不空。后面JDK9、10、11还会对这个类进行优化,可以暂且不用太关注。

发表评论

电子邮件地址不会被公开。 必填项已用*标注