Lamdba表达式

1.前言

Android中使用Rxjava越来越普遍。而Rxjava结合Lamdba表达式才真正实现代码简洁,所以在此为之后的Rxjava做铺垫,先说一下Lamdba表达式的使用。Lamdba表达式是jdk8之后支持的,主要针对简化匿名内部类代码。

2.环境搭建

为了让jdk8以下的环境使用Lamdba,这里先配置retroLambda插件向下支持。
在Project的build.gradle添加配置

    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
        classpath 'me.tatarka:gradle-retrolambda:3.6.1'
    }
    repositories {
        jcenter()
        mavenCentral()
    }

配置1
然后在module的build.gradle添加配置

apply plugin: 'me.tatarka.retrolambda'
android {
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

配置2

3.使用Lamdba表达式

使用前提

Lamdba表达式主要是用来简化匿名内部类,匿名内部类可以是接口也可以是抽象类,但是有一个前提条件:必须只有一个抽象方法。这样Lambda表达式就可以推断出你简化前的代码

3.1 基本使用: ->

当匿名内部类只有一个抽象方法,此方法可以有返回值,也可以没有返回值,Lambda认为没有必要非要写出这个匿名内部类及方法名,下面直接看例子:

     new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "run:_Lambda ");
            }
        }).start();

那么Lamdba表达式如何简化Runnable这个匿名内部类呢?且看:

 new Thread(()-> {Log.d(TAG, "run:_Lambda ");}).start();

可以看到,是如此得简单,规则如下:保留匿名内部类的参数即run方法的 ( ) 和方法体 {Log.d(TAG, “run:_Lambda “);} ,中间使用 -> 连接。即

(参数)->{方法体;}

如果方法体只有一行代码,还可以再简化

new Thread(()-> Log.d(TAG, "run:_Lambda ")).start();
(参数)->一行方法

再举一个常见的例子:常见的点击事件

    mTv.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               finish();
           }
       });

Lambda表达式简化:

   mTv.setOnClickListener((View v)-> {finish();});

方法体是一行,再次简化:

 mTv.setOnClickListener((View v)-> finish());

3.2 方法引用: ::

Lambda表达式利用 :: 引用类的方法,先看例子:
先构造一个类User:

public class User {
    private static final String TAG = "USER";
    private String userName;

    public User(View view) {
        Log.d(TAG, "method: 构造方法");
    }
    public static void sMethod(View view){
        Log.d(TAG, "method: 静态方法");
    }
    public void mMethod(View view){
        Log.d(TAG, "method: 成员方法");
    }

    public User() {
    }

    public User(String userName) {
        this.userName = userName;
    }

    public String getUserName() {
        return userName;
    }
}

注意类的方法的参数类型都是View。
3.2.1 Lambda表达式 :: 引用成员方法
先看之前的使用:

     User user = new User();
     mTv.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
             user.mMethod();
         }
     });

Lambda表达式 :: 简化

     User user = new User();
     mTv.setOnClickListener(user::mMethod);

之所以可以这样简化,关键就是匿名内部类OnClickListener中的onClick(View v)方法的参数和User的成员方法mMethod(View view)参数一样,这是使用 :: 的条件
3.2.1 Lambda表达式 :: 引用静态方法
之前的使用:

       mTv.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               User.sMethod(v);
           }
       });

Lambda表达式 :: 简化

    mTv.setOnClickListener(User::sMethod);

同样前提是:匿名内部类的参数和引用的静态方法参数类型一样
3.2.3 Lambda表达式 :: 引用构造方法
之前的使用:

       mTv.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               new User(v);
           }
       });

Lambda表达式 :: 简化

    mTv.setOnClickListener(User::new);

3.2.4 Lambda表达式 :: 类型上的成员方法引用
先看下使用

Function<User, String> getUserName = User::getUserName;

这里的规则是:类名::成员方法,需要注意的一点就是返回的是一个Function类型的,这种类型在什么时候用到呢

        Comparator comparator = Comparator.comparing(new Function<User, String>() {
            @Override
            public String apply(User user) {
                return user.getUserName();
            }
        });

于是这些代码就可以简化为

Comparator comparator = Comparator.comparing(User::getUserName);

Lambda表达式,对静态方法可以直接引用

Comparator comparator = comparing(User::getUserName);

除了以上的这些引用,还有

父类类上的成员方法引用:super::methodName 
数组构造方法引用:TypeName[]::new

同样前提是:匿名内部类的参数和引用的构造方法参数类型一样

3.3 Lambda表达式:forEach

Lambda表达式:forEach主要针对的是一些for循环while循环的简化
看下我们之前的写法(增强for):

        List<User> users = Arrays.asList(new User[]{new User("Mr.zhang_1"),new User("Mr.zhang_2")});
        for (User user : users){
            Log.d(TAG, "_Lambda3: user"+user.getUserName());
        }

Lambda表达式:forEach简化:

        List<User> users = Arrays.asList(new User[]{new User("Mr.zhang_1"),new User("Mr.zhang_2")});
        users.forEach(user ->Log.d(TAG, "_Lambda3: user"+user.getUserName()));

这里需要注意一下:forEach要求 minSdkVersion >=24。

3.4 Lambda表达式综合小例子

下面我们实现将一个List 按照用户名就行排序
看下之前的写法:

    List<User> users = Arrays.asList(new User[]{new User("Mr.zhang_1"),new User("Mr.zhang_2")});
        Collections.sort(users, new Comparator<User>() {
            @Override
            public int compare(User u1, User u2) {
                return u1.getUserName().compareTo(u2.getUserName());
            }
        });

先看下Lambda表达式简化的结果:

users.sort(comparing(User::getUserName));

这样一下可能不太好看懂,下面解释下简化的过程:
① 去掉匿名内部类Comparator和方法名compare

        Collections.sort(users,(User u1, User u2) ->u1.getUserName().compareTo(u2.getUserName()));

②使用Comparator.comparing()进行比较

Collections.sort(users,Comparator.comparing((User u)->u.getUserName()));

③这样静态方法可以直接引入

Collections.sort(users,comparing((User u)->u.getUserName()));

④Lambda类型推断

Collections.sort(users,comparing(u->u.getUserName()));

⑤ :: 双冒号方法引用

Collections.sort(users,comparing(User::getUserName));

⑥ 使用List的sort方法进一步简化

users.sort(comparing(User::getUserName));

这样就大功告成

demo地址:https://github.com/Mr-zhang0101/LambdaDemo.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值