02 JDK8函数式编程(上)
1、函数式编程基础
什么是函数式编程
• 一种编程范式
• 函数作为第一对象
• 注重描述而非具体执行步骤
• 更关心代数结构之间的关系
• 不可变
1.1 FP特点
• 不可变
• 惰性求值
• 闭包 :函数和函数内部能访问到的变量(也叫环境)的总和,就是一个闭包。
• 高阶函数
• 柯里化
• 部分应用
• 结合率
1.2 Lambda表达式基本语法
语法结构:
• 参数类型可推导
• 单行可省略大括号
• 单参数可省略小括号
private static Function<Integer, String> int2String = (Integer i) -> {return String.valueOf(i);};
private static Function<Integer, String> int2String_1 = (Integer i) -> String.valueOf(i);//只有一个表达式,可省略大括号
private static Function<Integer, String> int2String_2 = (i) -> String.valueOf(i);//参数类型可推导,可省略
private static Function<Integer, String> int2String_3 = i -> String.valueOf(i);//类型可推导且只有一个参数,可省略参数括号
思考: a -> b -> c -> d 代表什么
1.3 函数式接口
内置的常用函数式接口
private static Consumer run = System.out::println;//run.accept(xx);
private static Supplier<Integer> supplier = () -> 1;
private static Consumer<?> consumer = a -> {};
private static Predicate<?> predicate = a -> true;
private static Function<?, Boolean> fn = a ->true;
1.4 方法引用
-
静态方法 -> 需要告之属于哪个类
-
构造方法 -> 需要告之属于哪个类
-
指定实例方法 ->需要告之属于哪个实例
private Function<Integer, String> staticRef = LambdaBasic::int2StringFn; private static Supplier<LambdaBasic> constructor = LambdaBasic::new; private static Function<String, LambdaBasic> constructor2 = LambdaBasic::new;//type infer private BiFunction<Integer, Integer, String> instanceRef = this::twoint2String;
-
指定类型任意实例方法引用
2、函数式编程进阶
2.1 Stream基础API
Stream VS List
- Stream 可以是无限的
- Stream可并行处理
- Stream可能延迟处理
创建Stream
- 静态数据 Stream.of()
- 容器 collection.stream()
- 动态 Stream.iterate() & Stream.generate ()
- 其他api: Files.lines()…
2.2 Filter/map/Reduce
reduce 实战
- 求和
public static int sum(Collection<Integer> list) {
return list.stream().reduce(0, (acc, curr) -> acc + curr);
}
//主函数
List<Integer> list = Arrays.asList(2,3,4,7,5);
System.out.println(sum(list));
- 求最大值/最小值
public static Integer max(Collection<Integer> list) {
return list.stream().reduce(Math::max).orElse(null);
}
-
串联成字符串
-
存放进collection
-
用reduce实现map
public static <T,R> List<R> map(List<T> list, Function<T,R> mapFn) {//mapFn.apply() == mapFn()
List<R> ret = new ArrayList<>();
return list.stream().reduce(ret, (acc, curr)->{
R newValue = mapFn.apply(curr);//mapFn(curr)
acc.add(newValue); //list.add(mapFn(curr))//map.put()
return acc;
},
(list1, list2) -> {list1.addAll(list2); return list1;} );
}
- 用reduce实现filter
public static <T, R> List<T> filter(List<T> list, Predicate<T> p) {
List<T> ret = new ArrayList<>();
return list.stream().reduce(ret, (acc, curr)->{
if (p.test(curr)) {
acc.add(curr);
}
return acc;
},
(list1, list2) -> {list1.addAll(list2); return list1;} );
}