Lambda的使用与实战

来源:互联网 发布:腾讯分析 没数据 编辑:程序博客网 时间:2024/06/07 10:19

简介
(下面的简介也可以自己百度,一般进来的都是想知道怎么去用,所以这里主要也是重点在用法与实战上)
Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。
Lambda表达式还增强了集合库。 Java SE 8添加了lambda表达式。 在本文中,我们将从简单到复杂的示例中见认识lambda表达式。
环境准备
如果还没有安装Java 8,那么你应该先安装才能使用lambda。 像NetBeans 和IntelliJ IDEA 一类的工具和IDE就支持Java 8特性,包括lambda表达式和其他特性。

android studio中使用lambda方法见:  android studio中使用lambda


Lambda表达式的语法
基本语法:
(方法参数) -> 返回值

(方法参数) ->{ 方法内的语句; }

Lambda 简单与漂亮的案例

 //没用使用lambda 的代码ArrayList<String> strs = new ArrayList<>();Collections.sort(strs, new Comparator<String>() {     @Override     public int compare(String s1, String s2) {         return s1.compareTo(s2);    }});

下面是使用了lambda后的效果

//4行代码只需要1句代码就搞定 Collections.sort(strs, String::compareTo);

Lambda 开始学习

上面的案例在后面会介绍到的.

为了更好的学习lambda 语法,我自己定义了一些接口,实现内部类,如下:

/** * @Des: 内部方法带1个参数 , 不带返回值 */public interface IParmas1<A> {    void call(A a);}/** * @Des: 内部方法带2个参数 , 不带返回值 */public interface IParmas2<A, B> {    void call(A a, B b);}/** * @Des: 内部方法带2个参数 , 带返回值 */public interface IParmas2AndReturn<A, B, R> {    R call(A a, B b);}

设置接口的监听,实现内部类

 //不带返回值内部类,1个参数Demo    public void setOnIParmas1Listener(IParmas1 ipamr) {    }    //不带返回值内部类,2个参数Demo    public void setOnIParmas2Listener(IParmas2 ipamr) {    }    //带返回值内部类,2个参数Demo    public void setOnIParmas2AndReturnListener(IParmas2AndReturn ipamr) {    }    //配合demo1测试    public void demo1Test(Object o) {    }    //配合demo2测试    public void demo2Test(Object o1, Object o2) {    }


Lambda 双冒号(::)的使用

lambda 还有一个很屌的写法,看得我都觉得轻飘飘的feel都有了,

 才发现原来java代码可以这么单纯的,来看看吧,我也是看到这个写法后才喜欢上lambda的.

那就是 lambda的双冒号(::)写法,lambda 双冒号写法前提条件是,方法接收的值是参数原值,没有拼接其他数据,

额,不明白是吧,开始我也是云里雾里,接着看下面解释吧:

1.这是订阅IParmas1 接口的一个监听.

setOnIParmas1Listener(IParmas1 ipamr)

 2.在{@link IParmas1}  接口中定义的方法参数(A a),也就是Object.

void call(A a);

3.因此在接收内部类方法参数,也就是demo1Test(Object o),该方法的参数也是obj 

demo1Test(Object o)
4.这样条件下就可以直接把下面的,案例1,写成带双冒号lambda 语法了

setOnIParmas1Listener(this::demo1Test);  //(案例1的lambda写法)

多参数双冒号写法,见demo2的案例2.


Demo1 - 双冒号

//TODO 案例1,方法内部实现使用统一参数类型 原始写法setOnIParmas1Listener(new IParmas1() {    @Override    public void call(Object o) {        ParmasImpl.this.demo1Test(o);    }});//lambda 写法setOnIParmas1Listener(this::demo1Test);//TODO 案例2,不带返回值 原始写法setOnIParmas1Listener(new IParmas1() {    @Override    public void call(Object s) {        ParmasImpl.this.demo2();    }});// 不带返回值的lambda写法setOnIParmas1Listener(s -> demo2());

Lambda 匿名内部类的使用

使用lambda 来美化匿名内部类的高度,看起来简单又优雅

lambda 会直接把整个内部类隐藏,只留下形参,而且有一点要注意,内部类使用lambda,

前提是,该内部类只有一个内部方法,如果有两个或以上则使用不了lambda语法:

1. 空参数 写法: () -> 内部类方法的实现.

2. 1参数(String) 写法: s -> 内部类方法的实现.

需要注意的是当参数为Void时,写法与有1个参数的一样

3. 2个参数(String,int) 写法: (s,i) -> 内部类方法的实现.

lambda的 内部类写法与泛型没有太大关系,但是也要注意器参数是否被引用.

如果引用的话,其实lambda 是不推荐使用表达式的,但是也可以用,就是在用

的时候,他会自动将类型转换成Object

如写法1中: s 和 i 现在其实是 obj类型

写法1:

setOnIParmas2Listener((s, i) -> {    System.out.println(s + "-----" + i);});

写法2:当然也可声明类型

而且声明参数类型,只有参数在两个或以上才可以,一个参数是不可以声明的.

setOnIParmas2Listener((Object s,Object  i) -> {    System.out.println(s + "-----" + i);});

Demo2 - 匿名内部类

//TODO 案例1: 原始代码setOnIParmas2Listener(new IParmas2<String, Integer>() {    @Override    public void call(String s, Integer i) {        System.out.println(s + "-----" + i);    }});//使用lambda //因为上面其实是确定了类型的,被sout引用了,但是如果强制使用lambda的话//会出现方法参数自动转向默认obj类型setOnIParmas2Listener((s,i)-> System.out.println(s + "-----" + i));//TODO 案例2:多参数使用 lambda双冒号setOnIParmas2Listener(new IParmas2() {    @Override    public void call(Object o1, Object o2) {        ParmasImpl.this.demo2Test(o1, o2);    }});//使用lambdasetOnIParmas2Listener(this::demo2Test);

Lambda 方法带返回值的使用

 在有返回值的时候有两种情况,下面使用带两个参数的内部方法来示范

 1.内部方法直接返回,只有一个实现(方法/语句)

 (s,i) ->  null;

 其实这个写法就跟返回值是void的一样,只是void返回值方法内实现一个(方法/语句)而已,

 如demo1的案例2,中的lambda写法.

 s -> demo2()

 2.内部方法返回, 2个以上实现(方法/语句)

 (s,i) ->  { System.out.println("带了一个sout的实现");   return null; };

Demo2R - 带返回值

 //TODO 带返回值的原始方法setOnIParmas2AndReturnListener(new IParmas2AndReturn<String, Integer, Double>() {    @Override    public Double call(String s, Integer i) {        System.out.println("带了一个sout的实现");        return null;    }});//使用lambda 写法setOnIParmas2AndReturnListener((s, i) -> {    System.out.println("带了一个sout的实现");    return null;});


实际代码中实战用法

在上面demo 中已经说过了lambda 的一些常用方法,

下面是在实际中 对集合数据排序时的用法:

首先我们分析下Collections.sort(); 功能中参数内部类方法.

内部类Comparator ,默认内部方法compare(s1,s2)参数类型是String,带返回值int.

这样我们心里就大概知道lambda 该怎么去写或者这样写表达是上面意思.

 //没用使用lambda 的代码ArrayList<String> strs = new ArrayList<>();Collections.sort(strs, new Comparator<String>() {    @Override    public int compare(String s1, String s2) {        return s1.compareTo(s2);    }});//使用lambda 语法后,简单好看/** * this::demo1Test 与 String::compareTo 区别 * * 表达的就是当前类下的demo1Test(obj,obj)方法, * 其实你如果直接引用compareTo 方法也是可以的,那你就不可以用this了, * 而是使用String 对象,因此compareTo 在String 对象内. */// 1.1 使用匿名内部类根据values 排序 strsCollections.sort(strs, this::demoTest);// 1.2 使用匿名内部类根据values 排序 strsCollections.sort(strs, String::compareTo);// 2 使用lambda根据values  排序 strsComparator<String> sortByName = (s1, s2) -> (s1.compareTo(s2));Collections.sort(strs, sortByName);// 3 也可以采用声明形参的写法:Collections.sort(strs, (String s1, String s2) -> (s1.compareTo(s2)));

下面是demoTest(String,String)的方法

 /** * 提出比较的方法出来,方便lambda的双冒号写法调用 */private int demo1Test(String s1, String s2) {    return s1.compareTo(s2);}

demo代码:

github

2 0
原创粉丝点击