1. Lambda 表达式 2. 函数式接口 3. 方法引用与构造器引用 4. Stream API 5. 其他新特性
速度更快 代码更少(增加了新的语法 Lambda 表达式) 强大的 Stream API 便于并行 最大化减少空指针异常 Optional
Lambda 是一个匿名函数
在Java 语言中引入了一个新的语法元 素和操作符。这个操作符为 “->” , 该操作符被称 为 Lambda 操作符或剪头操作符。它将 Lambda 分为 两个部分: 左侧:指定了 Lambda 表达式需要的所有参数 右侧:指定了 Lambda 体,即 Lambda 表达式要执行 的功能。
语法格式一:无参,无返回值,Lambda 体只需一条语句
Runnable r1 = () → System.out.println("hello world");
语法格式二:Lambda 需要一个参数
Consumer<String> fun = (args) → System.out.println(args);
语法格式三:Lambda 只需要一个参数时,参数的小括号可以省略
Consumer<String> fun = args → System.out.println(args);
语法格式四:Lambda 需要两个参数,并且有返回值
BinaryOperator<Long> bo = (x, y) → {
System.out.println("hello world");
reurn x + y;
}
语法格式五:当 Lambda 体只有一条语句时,return 与大括号可以省略
BinaryOperator<Long> bo = (x, y) → x + y;
语法格式六:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
BinaryOperator<Long> bo = (Longx, Long y) → {
System.out.println("hello world");
reurn x + y;
}
类型推断: 上述 Lambda 表达式中的参数类型都是由编译器推断 得出的。Lambda 表达式中无需指定类型,程序依然可 以编译,这是因为 javac 根据程序的上下文,在后台 推断出了参数的类型。Lambda 表达式的类型依赖于上 下文环境,是由编译器推断出来的。这就是所谓的 “类型推断”
(1) 只包含一个抽象方法的接口,称为函数式接口。 (2) 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方 法上进行声明)。 (3) 我们可以在任意函数式接口上使用 @FunctionalInterface 注解, 这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包 含一条声明,说明这个接口是一个函数式接口。
@FounctionalInterface
public interface MyNumber {
public double getValue();
}
@FounctionalInterface
public interface MyNumber<T> {
public T getValue(T t);
}
ListenableFuture<Integer> speechTechniqueMacdFuture = executorService.submit( () -> 1+1);
函数式接 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer<T>消费型接口 | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
Supplier<T>供给型 | 无 | T | 返回类型为T的对象,包含方法:T get(); |
Function<T, R>函数型 | T | R | 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t) |
Predicate<T>断定型 | T | boolea | 确定类型为T的对象是否满足某约束,并返回boolean 值。包含方法boolean test(T t) |
方法引用:使用操作符 “::” 将方法名和对象或类的名字分隔开来
对象::实例方法
类::静态方法
类::实例
Function<Integer, Integer[]> in = Integer[]::new;
.stream().sorted(Comparator.comparingLong(ConditionAllVO::getStockTotalCount).reversed()).collect(Collectors.toList()))
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列“集合讲的是数据,流讲的是计算
注意:
(1)Stream 自己不会存储元素。
(2)Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
(3)Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
Lists.newArrayList().stream() : 返回一个顺序流
Lists.newArrayList().parallelStream() : 返回一个并行流
Arrays.stream(new Integer[1]).count();
Stream stream = Stream.of(Lists.newArrayList());
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,
否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。
筛选
方 法 | 描述 |
---|---|
filter(Predicate<T> p) | 接收 Lambda , 从流中排除某些元素。 |
distinct() | 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复 |
limit(long maxSize) | 截断流,使其元素不超过给定数 |
skip(long n) | 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补 |
映射
方 法 | 描述 |
---|---|
map(Function f) | 接收一个函数作为参数,该函数会被应用到每个素上,并将其映射成一个新的 |
mapToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream。 |
mapToInt(ToIntFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream |
mapToLong(ToLongFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream |
flatMap(Function f)flatMapToDouble(Function f)flatMapToInt(Function f)flatMapToLong(Function f) | 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流 |
排序
方 法 | 描述 |
---|---|
sorted() | 产生一个新流,其中按自然顺序 |
sorted(Comparator comp) | 产生一个新流,其中按比较器顺序 |
查找与匹配
方 法 | 描述 |
---|---|
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<T> |
收集
方 法 | 描述 |
---|---|
collect(Collector c) | 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法 |
方法 | 返回类型 | 作用 |
---|---|---|
toList | List<T> | 把流中元素收集到List:list.stream().collect(Collectors.toList()); |
toSet | Set<T> | 把流中元素收集到Set:list.stream().collect(Collectors.toSet()); |
toCollection | Collection<T> | 把流中元素收集到创建的集合:list.stream().collect(Collectors.toCollection(ArrayList::new)); |
counting | Long | 计算流中元素的个数:list.stream().collect(Collectors.counting()); |
summingInt | Integer | 对流中元素的整数属性求和:list.stream().collect(Collectors.summingInt(类名::属性名)); |
averagingInt | Double | 计算流中元素Integer属性的平均值:list.stream().collect(Collectors.averagingInt(类名::属性名)); |
summarizingIntsummarizingLongsummarizingDouble | IntSummaryStatistics | 收集流中Integer属性的统计值:list.stream().collect(Collectors.summarizingInt(类名::属性名));一次性得到元素个数、总和、均值、最大值、最小值 |
joining | String | 连接流中每个字符串:list.stream().map(类名::属性名).collect(Collectors.joining()); |
maxBy | Optional<T> | 根据比较器选择最大值:list.stream().collect(Collectors.maxBy(comparingInt(类名::属性名))); |
minBy | Optional<T> | 根据比较器选择最小值:list.stream().collect(Collectors.minBy(comparingInt(类名::属性名)) |
reducing | 归约产生的类型 | 从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值list.stream().collect(Collectors.reducing(0, 类名::属性名, Integer::sum)); |
collectingAndThen | 转换函数返回的类型 | 包裹另一个收集器,对其结果转换函数:list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size)); |
groupingBy 根据 | Map<K,V> | 某属性值对流分组,属性为K,结果为V:list.stream().collect(Collectors.groupingBy( 类名::属性名)); |
partitioningBy | Map<Boolean, List<T>> | 根据true或false进行分区:list.stream().collect(Collectors.partitioningBy(类名::属性名) |
并行流就是把一个内容分成多个数据块,并用不同的线程分 别处理每个数据块的流。 Java 8 中将并行进行了优化,我们可以很容易的对数据进行并 行操作。Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流之间进行切换。
Optional<T> 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在, 原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且 可以避免空指针异常。 常用方法: Optional.of(T t) : 创建一个 Optional 实例 Optional.empty() : 创建一个空的 Optional 实例 Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例 isPresent() : 判断是否包含值 orElse(T t) : 如果调用对象包含值,返回该值,否则返回t orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值 map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty() flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
云服务器,云硬盘,数据库(包括MySQL、Redis、MongoDB、SQL Server),CDN流量包,短信流量包,cos资源包,消息队列ckafka,点播资源包,实时音视频套餐,网站管家(WAF),大禹BGP高防(包含高防包及高防IP),云解析,SSL证书,手游安全MTP,移动应用安全、 云直播等等。