lambda表达式记录

这是一个别人文章的记录,详情请转往链接所在的地址
http://zh.lucida.me/blog/java-8-lambdas-insideout-language-features/

摘要:
1、lambda 表达式的参数类型可以从目标类型中得出

Comparator<String> c = (s1, s2) -> s1.compareToIgnoreCase(s2);

在上面的例子里,编译器可以推导出 s1 和 s2 的类型是 String

2、lambda 表达式只能出现在目标类型为函数式接口的上下文中,函数式接口

我们把这些只拥有一个方法的接口称为 函数式接口。(之前它们被称为 SAM类型,即 单抽象方法类型(Single Abstract Method)),我们并不需要额外的工作来声明一个接口是函数式接口:编译器会根据接口的结构自行判断(判断过程并非简单的对接口方法计数:一个接口可能冗余的定义了一个 Object 已经提供的方法,比如 toString(),或者定义了静态方法或默认方法,这些都不属于函数式接口方法的范畴)。不过API作者们可以通过 @FunctionalInterface 注解来显式指定一个接口是函数式接口(以避免无意声明了一个符合函数式标准的接口),加上这个注解之后,编译器就会验证该接口是否满足函数式接口的要求。

3、函数式接口的名称并不是 lambda 表达式的一部分。那么问题来了,对于给定的 lambda 表达式,它的类型是什么?答案是:它的类型是由其上下文推导而来。例如,下面代码中的 lambda 表达式类型是 ActionListener:
ActionListener l = (ActionEvent e) -> ui.dazzle(e.getModifiers());
以下是拥有目标类型上下文的一些情况:

变量声明
赋值
返回语句
数组初始化器
方法和构造方法的参数
lambda 表达式函数体
条件表达式(? :)
转型(Cast)表达式
这里面都可以使用lambda表达式

4、为了是这些新特性能够很好的融入到原有的类库里面,java8采用了默认方法,默认方法是写在接口里面的方法,并且有了自己的实现,所以会出现棱形继承的冲突,以下有几个规则可以解决默认方法的冲突问题

1、类的方法(class method)声明优先于接口默认方法。无论该方法是具体的还是抽象的。
2、被其它类型所覆盖的方法会被忽略。这条规则适用于超类型共享一个公共祖先的情况。
3、当两个独立的默认方法相冲突或是默认方法和抽象方法相冲突时会产生编译错误。这时程序员需要显式覆盖超类方法。一般来说我们会定义一个默认方法,然后在其中显式选择超类方法:

 Robot implements Artist, Gun {
  default void draw() { Artist.super.draw(); }
}

以下是一个总结过程

public class lambdaUse {
    static class Person implements Serializable {
        private int age;
        private String name;
        public Person() {
        }
        public Person(int age, String name) {
            this.age = age;
            this.name = name;
        }
        public String getLastName(){
            return this.name;
        }
    }
    static List<Person> srcList;
    static {
        srcList=new ArrayList<Person>();
        Person p1=new Person(20,"123");
        Person p2=new Person(21,"ABC");
        Person p3=new Person(22,"abc");
        srcList.add(p1);
        srcList.add(p2);
        srcList.add(p3);
    }
    public static void main(String[] args) {
        List<Person> people = srcList;
        //这是匿名内部类的实例化方式
        Collections.sort(people, new Comparator<Person>() {
            public int compare(Person x, Person y) {
                return x.getLastName().compareTo(y.getLastName());
            }
        });

        //使用lambda表达式之后
        // 尽管代码简洁了很多,但它的抽象程度依然很差:开发者仍然需要进行实际的比较操作
        // (而且如果比较的值是原始类型那么情况会更糟),
        // 所以我们要借助 Comparator 里的 comparing 方法实现比较操作:
        Collections.sort(people, (Person x, Person y) -> x.getLastName().compareTo(y.getLastName()));

        //这是使用了Comparator 里的 comparing 方法返回了一个lambda表达式
        Collections.sort(people, comparing((Person p) -> p.getLastName()));


        //    在类型推导和静态导入的帮助下,我们可以进一步简化上面的代码:
        Collections.sort(people, comparing(p -> p.getLastName()));

//        我们注意到这里的 lambda 表达式实际上是 getLastName 的代理(forwarder),于是我们可以用方法引用代替它:
        Collections.sort(people, comparing(Person::getLastName));

// 最后,使用 Collections.sort 这样的辅助方法并不是一个好主意:它不但使代码变的冗余,也无法为实现 List 接口的数据结构提供特定(specialized)的高效实现,\
// 而且由于 Collections.sort 方法不属于 List 接口,用户在阅读 List 接口的文档时
// 不会察觉在另外的 Collections 类中还有一个针对 List 接口的排序(sort())方法。
//  默认方法可以有效的解决这个问题,我们为 List 增加默认方法 sort(),然后就可以这样调用:
        people.sort(comparing(Person::getLastName));

// 此外,如果我们为 Comparator 接口增加一个默认方法 reversed()(产生一个逆序比较器),
// 我们就可以非常容易的在前面代码的基础上实现降序排序。
        people.sort(comparing(Person::getLastName).reversed());

    }



}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值