Lambda表达式
- What:java8引入的语法结构
- Why:简化匿名内部类
- How:
- 格式: Runnable runnable2 = () -> {…}; //…表示被覆盖的方法
- ()代表方法的参数列表,-> 转向符,表示参数如何被处理,右面就时被处理的细节
Runnable runnable = () -> {System.out.println("hello");}
- 使用范围,函数式接口创建匿名内部类时
- 原理,类型推断(新特性)
- 可省略
- 方法体只有一个语句时,return可省略
- 一个语句可省略大括号
- 一个参数可省略小括号,类型名
- 两个参数只能省略参数类型
- 凡是可推断的都可省略
接口
- static, 允许有静态方法,也有方法体,静态方法的作用就是通过接口类来调用,适用于接口都的功能性增强,调用简单。
- default, 允许有默认方法,也有方法体,作用时增强接口的功能性,并且在不改变原有子类的情况下做到向抽象类靠拢。
- 接口类型(java8提出接口类型概念用于流处理)
- 消费型接口 : 只进行方法执行,没有返回值。
- 供给型接口 :
- 函数型接口 :
- 断定型接口 :
函数式接口和分类
- 只有一个抽象方法的接口
- 支持泛型
- 对一些特定的方法行为模式的抽象
- Consumer 是消费器,给它传一个对象,没有返回
- Supplier 是供给器,只需要调用它,则能返回T类型对象,(无参构造器)
- Function<T, R> 是装饰器,需要t类型的对象,经过某种处理之后返回r型的对象
- Predicate 是断定器,需要一个T类型的对象,经过某种判断,返回真或假,有参,返回布尔值
- 其他接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|
BiFunction<T, U, R> | T, U | R | 对类型为 T, U 参数应用操作,返回 R 类型的结果。包含方法为 R apply(T t, U u); |
UnaryOperator (Function子接口) | T | T | 对类型为T的对象进行一元运算,并返回T类型的结果。包含方法为 T apply(T t); |
BinaryOperator (BiFunction 子接口) | T, T | T | 对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为 T apply(T t1, T t2); |
BiConsumer<T, U> | T, U | void | 对类型为T, U 参数应用操作。包含方法为 void accept(T t, U u) |
BiPredicate<T,U> | T,U | boolean | 包含方法为 boolean test(T t,U u) |
ToIntFunction ToLongFunction ToDoubleFunction | T | int long double | 分别计算int、long、double、值的函数 |
IntFunction LongFunction DoubleFunction | int long double | R | 参数分别为int、long、double 类型的函数 |
- 面向函数式编程,引入方法变量(引用),可以使用简单的方法操作成为复杂的方法
- 方法引用
- 只要接口中的方法模式和已有方法一样,就可以直接使用已有方法作为实现!!!
- 对象::实例方法名
- 类::静态方法名
- 类::实例方法名
//举例,消费者模式。
Consumer<String> c1 = System.out::println;
c1.accept("124");
Stream api
特点
- 对象流,处理批量对象的思路
- 对集合中的批量数据进行sql类似的方式进行处理
- 重点是计算,处理
- 不是集合,而是流
2. stream不会改变源对象,会返回持有结果的新对象
3. Stream操作时延迟执行的,先积攒后执行,提供效率
4. Stream只能消费一次,类似于Thread
5. 高级iterator一次,不可往复,数据只能遍历一次,但是可以并行化数据。
- 工作窃取,多线程处理数据可以协调处理
步骤
创建
- 基于集合:集合对象.stream()
- 基于数组:Arrays.stream(arr)
- 基于散数据:Stream.of(T…values);
- 无限流Stream.gemerate(Supplier sup);
中间操作,任务开始执行,相当于Thread里的start方法
- Stream filter(Predicate p)接受lambda,把流中的每个对象经过判定器,为真留下,假的丢弃
- Stream distinct(); 筛选器,去重,使用equal和hashcode去重
- limit(long maxSize); 截断流,限制个数
- skip(long n); 跳过元素,跳过前n个元素
- sorted(); 自然排序
- sorted(Comptaretor c); 定制排序,加比价器
- map(Funtion f); 映射,使用转换器
map(Function f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。 |
---|
mapToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream。 |
mapToInt(ToIntFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream。 |
mapToLong(ToLongFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream。 |
flatMap(Function f) | 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流 |
终止操作
1. foreach(Consumer consumer);把每个数据经过消费器消费。
匹配与查找
方法 | 描述 |
---|
allMatch(Predicate p) | 检查是否匹配所有元素 |
anyMatch(Predicate p) | 检查是否至少匹配一个元素 |
noneMatch(Predicate p) | 检查是否没有匹配所有元素 |
findFirst() | 返回第一个元素 |
findAny() | 返回当前流中的任意元素 |
查找遍历
方法 | 描述 |
---|
count() | 返回流中元素总数 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最小值 |
forEach(Consumer c) | 内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了) |
归约,归纳,把逐渐每个元素拿出来运算
方法 | 描述 |
---|
reduce(T iden, BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回 T |
reduce(BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回 Optional |
//基于集合
public void test4() {
List<Student> list = StudentData.getList();
Stream<Student> stream = list.stream();
stream.forEach(System.out::println);
}
//基于无限流
public void test3() {
Stream<Double> stream = Stream.generate(() -> Math.random());
stream.forEach(System.out::println);
}
//基于散数据
public void test2() {
Stream<String> of = Stream.of("123", "agasd", "12a", "asdfa");
of.forEach(System.out::println);
}
//基于数组数组
public void test1() {
List<Student> list = StudentData.getList();
Student[] students = null;
list.toArray(students);
Stream<Student> stream = Arrays.stream(students);
stream.forEach(System.out::println);
}
//举例:
public class Main4 {
@Test
public void test1() {
//Student泛型传递
List<Student> list = StudentData.getList(); //StudentDate的静态方法可拿到javaBean类:Student.
//.筛选器.筛选器.排序.限制器.终止操作。
list.stream().filter(t -> t.getGrade() == 3).filter(t -> t.getScore() < 60).sorted().limit(3).forEach(System.out::println);
}
}
并行
Optional 类
- 最大渐少空指针异常
- Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。
-常用方法:
- Optional.empty() : 创建一个空的 Optional 实例
- Optional.of(T t) : 创建一个 Optional 实例
- Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
- isPresent() : 判断是否包含值
- T get(): 如果调用对象包含值,返回该值,否则抛异常
- orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
- orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
- map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
- flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
- 待续。。。