编辑推荐: |
本文主要介绍了java新特性,Lambda表达式及Stream API相关知识。希望能对遇到类似问题的同学有所帮助。
本文来自于CSDN,由火龙果软件Linda编辑、推荐。 |
|
Lambda表达式
什么是Lambda表达式?
可以将Lambda表达式理解为一个匿名函数;允许将函数像变量那样作为实参传递给另一个函数; 这就是函数式编程,函数是一等公民。
为什么要引入Lambda表达式?
Lambda表达式能够让程序员的编程更加高效
举例分析有多高效:
public class TestLambda {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
thread.close();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("Hello");
}
}
|
为了使这段代码变得更加简洁,可以使用匿名内部类重构一下
package com.isea.java;
public class TestLambda {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
}).start();
}
}
|
上面的代码可以换成这样的,我们将new 的接口,赋值给线程的引用:
public class TestLambda {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
});
thread.start();
}
}
|
而上面的这段代码,不是最简单的,还可以进一步简化
public class TestLambda {
public static void main(String[] args) {
new Thread(() -> System.out.println("Hello")).start();
}
}
|
这就是lambda的魅力!
lambda表达式六大语法类型推断
有没有发现,上述 Lambda 表达式中,我们没有手动指定参数类型,参数类型都是由编译器推断得出的。
为什么可以这样写呢?这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。这就是所谓的“类型推断”。
Lamda 表达式不能修改局部变量值
我们可以直接在 lambda 表达式中访问外部的局部变量:
final int num = 1;
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from + num);
stringConverter.convert(2);
|
下面的就无法编译:
int num = 1;
Converter<Integer, String> stringConverter =
(from) -> String.valueOf(from + num++);
|
Stream API
Stream被翻译为流,它的工作过程像将一瓶水导入有很多过滤阀的管道一样,水每经过一个过滤阀,便被操作一次,比如过滤,转换等,最后管道的另外一头有一个容器负责接收剩下的水。
示意图如下:
首先通过source产生流,然后依次通过一些中间操作,比如过滤,转换,限制等,最后结束对流的操作。
Stream也可以理解为一个更加高级的迭代器,主要的作用便是遍历其中每一个元素。
Stream的好处:
Stream作为Java 8的一大亮点,它专门针对集合的各种操作提供各种非常便利,简单,高效的API
Stream API主要是通过Lambda表达式完成,极大的提高了程序的效率和可读性,同时Stram
API中自带的并行流使得并发处理集合的门槛再次降低,使用Stream API编程无需多写一行多线程的大门就可以非常方便的写出高性能的并发程序。使用Stream
API能够使你的代码更加优雅。
Stream的特点
Stream 自己不会存储元素。
Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
Stream 操作三个步骤
1、 创建 Stream
一个数据源(如:集合、数组),获取一个流
2、 中间操作
一个中间操作链,对数据源的数据进行处理
3、终止操作(终端操作)
一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用 Stream的创建方式
创建 Stream方式一:通过集合
Java8 中的 Collection 接口被扩展,提供了两个获取流的方法:
接口
Stream<E> stream() : 返回一个顺序流
Stream<E> parallelStream() : 返回一个并行流
举例:employees是一个list
Stream<Employee> stream = employees.stream();
Stream<Employee> parallelStream = employees.parallelStream();
|
创建 Stream方式二:通过数组
static <T> Stream<T> stream(T[] array): 返回一个流
IntStream stream = Arrays.stream(arr);
|
创建 Stream方式三:通过Stream的of()
可以调用Stream类的静态方法 of(), 通过显示值创建一个流。它可以接收任意数量的参数。
public static<T> Stream<T> of(T... values) : 返回一个流
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
|
创建 Stream方式四:创建无限流
1、迭代
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
2、生成
public static<T> Stream<T> generate(Supplier<T> s)
Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
Stream.generate(Math::random).limit(10).forEach(System.out::println);
|
Stream 的中间操作
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。
筛选和切片
举例
stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);
list.stream().limit(3).forEach(System.out::println);
|
映射
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
list.stream().map(str -> str.toUpperCase()).forEach(System.out::print);
|
排序
List<Integer> list = Arrays.asList(12, 43, 65, 34, 87, 0, -98, 7);
list.stream().sorted().forEach(System.out::println);
|
list对象所属的类如果没有实现Comparable接口的话,就会无法排序而报错。
Stream 的终止操作
终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:Integer、String、List、Map,甚至是
void 。
流进行了终止操作后,不能再次使用。
collect 收集汇总
collect(Collector c)
接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
Collector 接口中方法的实现决定了如何对流执行收集的操作(如收集到 List、Set、 Map)。
另外, Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表: 练习1
查找工资大于6000的员工,结果返回为一个List或Set
List<Employee> employeeList = employees.stream()
.filter(e -> e.getSalary() > 6000)
.collect(Collectors.toList());
|
练习2
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
Map<String, List<String>> collect = list.stream().collect(
Collectors.groupingBy(
str -> str
));
for (String s : collect.keySet()) {
System.out.println(s+" "+collect.get(s));
}
|
重点 规约
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, Integer::sum);
|
匹配与查找
|