Lambda

2018-05-21  本文已影响0人  ticktackdong

A.Hello Lambda

一.从匿名类演变成Lambda表达式

1.匿名类写法
  HeroChecker c1 = new HeroChecker(){
       public boolean test(Hero h){
           return (h.hp>100 && h.damage<50)
        }
 };
2.把外面的壳子去掉只保留方法参数->方法体
 HeroChecker c2 = (Hero h)->{
      return h.hp>100 && h.damage<50;
 };
3.把return 和{}去掉
HeroChecker c3 = (Hero h)->h.hp>100 && h.damage<50;
4.把参数类型和圆括号去掉(只有一个参数时才可以去掉圆括号)
HeroChecker c4 = h->h.hp>100 && h.damage<50;
5.把c4作为参数传递进去
filter(heros,c4);
6.直接把表达式传递进去
filter(heros,h->h.hp>100&&h.damage<50)

二.匿名方法

与匿名类概念比较,Lambda其实就是匿名方法
这是一种把方法作为参数传递的编程思想
虽然代码是这么写的
 filter(heros,h->h.hp>100 && h.damage<50)
但是Java会在背后悄悄地把这些都还原成匿名类方式
引入Lambda表达式会使代码更加紧凑而不是各种接口和匿名类到处飞
弊端:
  可读性差,一旦变得比较长就难以理解
  不便于调试,很难在表达式中增加调试信息
  版本支持,JDK8以后支持

B.方法引用

1.引用静态方法
   首先为TestLambda添加一个静态方法
     public static boolean testHero(Hero h){
              return h.hp>100 && h.damage<50;
     }
     Lambda表达式中调用这个静态方法
         filter(heros,h->TestLambda.testHero(h));
         filter(heros,TestLambda::testHero);//写法二
2.引用对象方法
   与引用静态方法很类似,只是传递方法的时候需要一个对象的存在
   TestLambda testLambda = new TestLambda();
   filter(heros, testLambda::testHero);
3.引用容器中的方法
    首先为Hero添加一个方法
    public boolean matched(){
         return this.hp>100 && this.damage<50; 
   }
  filter(heros,h->h.matched());
  filter(heros,Herp::matched);//写法二
4.引用构造器
   有的接口中的方法会返回一个对象,比如java.util.function.Supplier提供了一个get方法,返回一个对象
 public interface Supplier<T>{
    T get();
 }
   设计一个方法,参数是这个接口
 public static List getList(Supplier<List> s){
       return s.get();
  } 
  为了调用这个方法有三种方式
   1.匿名类
        Supplier<List> s = new Supplier<List>(){
           public List get(){
                return new ArrayList();
               }        
           }
         List list1 = getList(s);
   2.Lambda表达式
      List list2 = getList(()->new ArrayList());
   3.引用构造器
      List list3 = getList(ArrayList::new);

C.聚合操作

1.Stream和管道的概念
 heros
   .stream()
   .filter(h -> h.hp > 100 && h.damage < 50)
   .forEach(h -> System.out.println(h.name));
Stream和Collection结构化的数据不一样, 
Stream是一系列的元素,就像生产线上的罐头一样,一串串的出来
管道是一系列的聚和操作又分为3部分
      管道源:
      中间操作:每个中间操作又会返回一个Stream。
              中间操作是懒操作,并不会进行真正的便利
      结束操作:是流的最后一个操作,当这个操作被执行完后流就被用光了,无法再被操作。
              不会返回Stream,但是会返回int,float,String,Collection或者什么都不返回。
              结束操作才进行真正的遍历,在遍历的时候才会去进行中间操作的相关判断
2.管道源
  把Collection切换成管道源很简单,调用stream()就行了
 heros.stream()
 但是数组却没有stream()方法,需要使用
   Arrays.stream(hs)或者Stream.of(hs)   
3.中间操作
 主要分为两类,对元素进行筛选和转换成其他形式的流
 对元素进行筛选:
     filter  匹配
     distinct 去除重复(根据equals判断)
     sorted 自然排序
     sorted(Comparator<T>) 指定排序
     limit 保留
     skip 忽略
转换为其他形式的流
    mapToDouble  转换成double的流
    map   转换成任意类型的流
4.结束操作
   常见结束操作如下:
      forEach() 遍历每个元素
      toArray() 转换为数组
      min(Comparator<T>) 取最小的元素
      max(Comparator<T>) 取最大的元素
      count() 总数
      findFirst() 第一个元素
上一篇下一篇

猜你喜欢

热点阅读