Java 8 Lambda 表达式和 Stream 操作,网易资深 Java 架构师
也可以类名::实例方法名, 如 String::substring
构造方法引用,通过类名::new, 如 User::new
第三点: 若 Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: 类名::实例方法名
There are several basic function shapes,
including Function (unary function from T to R), Consumer (unary function fro
m T to void), Predicate (unary function from T to boolean), and Supplier (nullary function to R).
Function shapes have a natural arity based on how they are most commonly used. The basic shapes can be modified by an arity prefix to indicate a different arity, such as BiFunction (binary function from T and U to R).
类名::方法名,相当于对这个方法闭包的引用,类似 js 中的一个 function。比如:
public static void main(String[] args) {
Consumer<String> printStrConsumer = DoubleColon::printStr;
printStrConsumer.accept("printStrConsumer");
Consumer<DoubleColon> toUpperConsumer = DoubleColon::toUpper;
toUpperConsumer.accept(new DoubleColon());
BiConsumer<DoubleColon,String> toLowerConsumer = DoubleColon::toLower;
toLowerConsumer.accept(new DoubleColon(),"toLowerConsumer");
BiFunction<DoubleColon,String,Integer> toIntFunction = DoubleColon::toInt;
int i = toIntFunction.apply(new DoubleColon(),"toInt");
}
static class DoubleColon {
public static void printStr(String str) {
System.out.println("printStr : " + str);
}
public void toUpper(){
System.out.println("toUpper : " + this.toString());
}
public void toLower(String str){
System.out.println("toLower : " + str);
}
public int toInt(String str){
System.out.println("toInt : " + str);
return 1;
}
}
复制代码
用::提取的函数,最主要的区别在于静态与非静态方法,非静态方法比静态方法多一个参数,就是被调用的实例。
// 使用双冒号::来构造非静态函数引用
String content = "Hello JDK8";
// public String substring(int beginIndex)
// 写法一: 对象::非静态方法
Function<Integer, String> func = content::substring;
String result = func.apply(1);
System.out.println(result);
// 写法二:
IntFunction<String> intFunc = content::substring;
result = intFunc.apply(1);
System.out.println(result);
// 写法三: String::非静态方法
BiFunction<String,Integer,String> lala = String::substring;
String s = lala.apply(content, 1);
System.out.println(s);
// public String toUpperCase()
// 写法一: 函数引用也是一种函数式接口,所以也可以将函数引用作为方法的参数
Function<String, String> func2 = String::toUpperCase;
result = func2.apply("lalala");
System.out.println(result);
// 写法二: 可以改写成 Supplier: 入参 void, 返回值 String
Supplier<String> supplier = "alalal"::toUpperCase;
result = supplier.get();
System.out.println(result);
复制代码
数组引用
// 传统 Lambda 实现
IntFunction<int[]> function = (i) -> new int[i];
int[] apply = function.apply(5);
System.out.println(apply.length); // 5
// 数组类型引用实现
function = int[]::new;
apply = function.apply(10);
System.out.println(apply.length); // 10
复制代码
Optional 的用法
c static void main(String[] args) {
// Optional 类已经成为 Java 8 类库的一部分,在 Guava 中早就有了,可能 Oracle 是直接拿来使用了
// Optional 用来解决空指针异常,使代码更加严谨,防止因为空指针 NullPointerException 对代码造成影响
String msg = "hello";
Optional<String> optional = Optional.of(msg);
// 判断是否有值,不为空
boolean present = optional.isPresent();
// 如果有值,则返回值,如果等于空则抛异常
String value = optional.get();
// 如果为空,返回 else 指定的值
String hi = optional.orElse("hi");
// 如果值不为空,就执行 Lambda 表达式
optional.ifPresent(opt -> System.out.println(opt));
复制代码
Stream 的一些操作
有些 Stream 可以转成集合,比如前面提到 toList,生成了 java.util.List 类的实例。当然了,还有还有 toSet 和 toCollection,分别生成 Set 和 Collection 类的实例。
final List<String> list = Arrays.asList("jack", "mary", "lucy");
// 过滤 + 输出
System.out.println("过滤 + 输出: ");
Stream<String> stream = list.stream();
stream.filter(item -> !item.equals("zhangsan"))
.filter(item -> !item.equals("wangwu"))
.forEach(item -> System.out.println(item));
// 限制为 2
System.out.println("limit(2): ");
list.stream().limit(2).forEach(System.out::println);
// 排序
System.out.println("排序: ");
list.stream().sorted((o1, o2) -> o1.compareTo(o2)).forEach(System.out::println);
// 取出最大值
System.out.println("max: ");
String result = list.stream().max((o1, o2) -> o1.compareTo(o2)).orElse("error");
评论