Java 8 函 数 式 编 程 Functional Programming 于 文 琦
Lambda λ 希 腊 字 母 表 中 第 十 一 位 物 理 上 的 波 长 符 号 线 性 代 数 中 的 特 征 值
About Functional Programming 什 么 是 函 数 式 编 程? 是 一 种 编 程 范 式, 是 如 何 编 程 的 方 法 论 (Methodology) 什 么 是 方 法 论? 方 法 论 是 哲 学 术 语, 简 单 说 就 是 用 什 么 样 的 方 式 来 处 理 问 题 百 度 百 科 : 方 法 论 是 普 遍 适 用 于 各 门 具 体 社 会 科 学 并 起 到 指 导 作 用 的 范 畴 原 则 理 论 方 法 和 手 段 的 总 和
函 数 式 编 程 的 知 识 结 构 ( 代 码 即 数 据 的 编 程 风 格 ) lambda 表 达 式 1 Stream2 自 定 义 类 库 3 Collectors 收 集 器 4 数 据 并 行 化 5
Lambda 表 达 式 Runnable noarguments=()-> System.out.println("Hello World."); noarguments.run(); Runnable multistatement=()-> { System.out.println("Hello World."); try { Integer.parseInt("AAA"); catch(numberformatexception e){ Scanner scanner=new Scanner(System.in); System.out.println(scanner.next()); ; multistatement.run(); Comparable comparable=object-> 1;// 编 译 器 可 根 据 上 下 文 推 断 出 object 的 类 型 Comparator comparator=(object x,object y)->{ if(x.hashcode()>y.hashcode()){// 伪 代 码 return 1; return 0; ;
值 传 递 和 函 数 接 口 String name="aaa"; Runnable value=()-> System.out.println("Hello World."+name); value.run(); name 就 是 一 个 既 成 事 实 的 final(effectively final) 变 量 (java8) 匿 名 内 部 类 要 引 用 外 部 变 量, 外 部 变 量 必 须 是 final 的 java8 放 开 了 这 个 限 制, 可 以 不 用 final 修 饰, 但 不 能 多 次 赋 值 * 函 数 接 口 : 是 只 有 一 个 抽 象 方 法 的 接 口 java.util.function Predicate(test) Consumer(accept) Function(apply) Supplier(get) UnaryOperator 继 承 Function BinaryOperator 继 承 BiFunction @FunctionalInterface public interface Runnable { * 未 标 记 FunctionalInterface 的 接 口 也 可 以 用 于 lambda 表 达 式
JDK8 之 前 已 有 的 函 数 式 接 口 java.lang.runnable java.util.concurrent.callable java.util.comparator java.lang.reflect.invocationhandler java.awt.event.actionlistener 有 的 接 口 并 没 有 标 注 @FunctionalInterface, 但 依 然 不 改 变 它 是 函 数 接 口 的 本 质 FI 注 解 会 检 查 是 否 只 有 一 个 待 实 现 的 方 法 ( 静 态 方 法, 默 认 方 法 除 外 )-java8 特 性
Stream Stream: 是 用 函 数 式 编 程 方 式 在 集 合 类 上 进 行 复 杂 操 作 的 工 具 List<String> list= new ArrayList(); list.add( A ); list.add( B ); cnt=list.stream().filter(str->str.equals( A )).count(); //Predicate for(string s:list){ if(s.equals("a")){ cnt++; 惰 性 求 值 方 法 (filter)vs 及 早 求 值 方 法 (count) List<String> blist=stream.of("a","b").map(string::tolowercase).collect(collectors.tolist());//function System.out.println(bList.equals(Arrays.asList("a","b"))); 区 别 :Functional Interface vs @FunctionalInterface vs Function
Stream Stream: 是 用 函 数 式 编 程 方 式 在 集 合 类 上 进 行 复 杂 操 作 的 工 具 Arrays.asList(3,1,2).stream().min(Comparator.comparing(i->i)).get();//Optional Arrays.asList(obj1,obj2).stream().max(Comparator.comparing(obj->obj.hashCode())).get(); BinaryOperator<Integer> add=(x,y)->x+y; int count=stream.of(1,2,3).reduce(add).get(); BinaryOperator<Integer> add=(x,y)->x+y; int count=stream.of(1,2,3).reduce(0,add); Map vs Reduce? Map: 将 一 组 值 转 换 为 另 一 组 值 Reduce: 从 一 组 值 中 生 成 一 个 值
For example 假 设 要 找 出 某 些 商 家 的 商 品 在 某 个 分 类 下 的 原 价 在 1500 以 上 的 折 扣 超 过 75% 的 商 品 编 号 flatmap filter filter map filter List<Integer> wareidlist=venderlist.stream().flatmap(vender -> vender.getwarelist()).filter(ware->ware.getcategory()==1).filter(ware -> ware.getprice() > 1500).filter(ware -> ware.getdiscount() > 75).map(Ware::getWareId)// 方 法 引 用 method reference.collect(tolist());
自 定 义 类 库 自 定 义 可 以 使 用 lambda 表 达 式 的 方 法 public void debug(supplier<string> message){ debug(message.get()); public void debug(string message){ System.out.println(message); JAVA8 new feature: Collection stream,iterable foreach default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); default void foreach(consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t);
接 口 的 默 认 方 法 的 继 承 静 态 方 法 类 胜 于 接 口 子 类 胜 于 父 类 接 口 继 承,Walk extends Move 接 口 实 现 类,WalkImpl 接 口 实 现 类 的 继 承 WalkImpl extends MoveImpl 多 重 实 现 类 RunImpl implements A,B Java 8 new feature:stream.of, Optional.of Optional<Integer> optional=optional.empty(); if(optional.ispresent()){ System.out.println(optional.get()); System.out.println(optional.orElse(1)); System.out.println(optional.orElseGet(()->2)); 用 Optional 类 型 代 替 null, 鼓 励 程 序 员 检 查 变 量 是 否 为 空
Collectors import static java.util.stream.collectors.tolist;// 静 态 引 入 List<Integer> wareidlist=venderlist.stream().flatmap(vender -> vender.getwarelist()).filter(ware->ware.getcategory()==1).filter(ware -> ware.getprice() > 1500).filter(ware -> ware.getdiscount() > 75).map(Ware::getWareId)// 方 法 引 用 method reference.collect(tolist()); tocollection, toset, tomap, toconcurrentmap, maxby, averagingint, partitionby, groupingby, joining, stream has already been operated upon or closed partitionby vs groupingby 组 合 收 集 groupingby($lambda,mapping)
自 定 义 Collector public class StringCollector implements Collector<String,StringCombiner,String> { private String append; private static final Set<Characteristics> characteristics = Collections.emptySet(); public StringCollector(String append){ this.append=append; @Override public Supplier supplier() { return ()->new StringCombiner(append); @Override public BiConsumer<StringCombiner,String> accumulator() { return StringCombiner::accumulate; @Override public BinaryOperator<StringCombiner> combiner() { return StringCombiner::merge; @Override public Function<StringCombiner,String> finisher() { return StringCombiner::toString; @Override public Set<Characteristics> characteristics() { return characteristics; skulist.stream().map(sku::getname).collect( new StringCollector("^") ); Since1.8 Map.computeIfAbsent Get? Put?
并 行 与 并 发 核 1(CPU) 核 2 A 图 核 1 核 2 B 图 任 务 1 任 务 2 任 务 1 任 务 1 任 务 2 任 务 1 任 务 3 任 务 1 与 任 务 2 是 并 发 处 理 任 务 1 与 任 务 3 是 并 行 处 理 任 务 2 任 务 2 任 务 2 与 任 务 3 是 并 行 处 理 并 发 但 不 并 行 并 发 且 并 行 并 发 : 多 个 任 务 共 享 时 间 段 并 行 : 多 个 任 务 同 一 时 间 发 生 数 据 并 行 化 : 是 指 将 数 据 分 成 快, 为 每 块 数 据 分 配 单 独 的 处 理 单 元
并 行 化 操 作 Stream.of(1,2,3).parallel().collect( ); List.parallelStream().collect( ); 性 能 好 :ArrayList, 数 组,IntStream.range 性 能 一 般 :HashSet,TreeSet 性 能 差 :LinkedList,Stream.iterate 无 状 态 性 能 好 :map,filter,flatmap 有 状 态 性 能 差 :limit,sorted,distinct int size=1000000; Seller[] sellers=new Seller[size]; Arrays.setAll(sellers, i -> new Seller(i,new BigDecimal(i+ Math.random()),1+i)); double ret=arrays.aslist(sellers).stream().maptodouble( seller -> seller.getprice().doublevalue() * seller.getrate()).sum(); Sequential vs Parallel 10000 条 :0.475 vs 0.558 100000 条 :1.132 vs 1.040 1000000 条 :9.770 vs 6.858 int size=1000000; Seller[] sellers=new Seller[size]; Arrays.parallelSetAll(sellers, i->new Seller(i,new BigDecimal(i+ Math.random()),1+i)); double ret=arrays.aslist(sellers).parallelstream().maptodouble( seller -> seller.getprice().doublevalue() * seller.getrate()).sum();
THANK YOU