Android 使用jdk1.8新特性之lambda表达式
目前Java 8的新特性Lambda 结合 RxJava 在一起使用可以简化大量的代码,下面简单介绍在AndroidStudio中配置Gradle使得支持Java 8。
Android 使用Java8 配置
添加插件retrolambda
在project层的build.gradle配置
buildscript { repositories { jcenter() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:2.2.0' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'me.tatarka:gradle-retrolambda:3.2.5' //添加插件retrolambda // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }}
配置android{}区块Jav//java版本8
compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8}
配置完成之后的build.gradle文件
buildscript { repositories { mavenCentral() } dependencies { classpath 'me.tatarka:gradle-retrolambda:3.2.4' //for java 8 lamda }}apply plugin: 'com.android.application'apply plugin: 'me.tatarka.retrolambda'android { compileSdkVersion 23 buildToolsVersion "23.0.1" defaultConfig { applicationId "com.mrljdx.sample" minSdkVersion 10 targetSdkVersion 23 versionCode 1 versionName "1.0" } //java版本8 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } .....//省略其他配置}dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') testCompile 'junit:junit:4.12' //java 8 配置 retrolambdaConfig 'net.orfjackal.retrolambda:retrolambda:+'}配置proguard.pro混淆文件## see https://github.com/evant/gradle-retrolambda for java 8-dontwarn java.lang.invoke.*
Lambda表达式
lambda表达式取代了匿名内部类,取消了模板,允许程序猿用函数式风格编写代码,使代码可读性更高,尽管刚开始你会看不懂,但是你应该尝试,毕竟这是新的东西,我已从中获益。
格式
基本格式是:() -> {}
有下面三种具体表达:
1.(params) -> expression
2.(params) -> statement
3.(params) -> {statement}
使用Java 8 lambda表达式进行事件处理
传统的点击事件,应用匿名内部类:
Button button = new Button(mContext); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext, "button click", Toast.LENGTH_SHORT).show(); } }); }
如果按照之前Studio配置好了的话会有提示:
使用lambda表达式之后是这样的
button.setOnClickListener(v -> Toast.makeText(mContext, "button click", Toast.LENGTH_SHORT).show());
一行代码就搞定了,清晰可见,把行为传到了函数里,这里注意v不可省略,是函数onClick的参数;
传统实现Runnable接口是这样的:
new Thread(new Runnable() { @Override public void run() { Log.i("TAG", "haha"); }}).start();
使用lambda表达式之后是这样的:
new Thread(() -> { Log.i("TAG", "haha");}).start();
使用lambda表达式对列表进行迭代
List<String> features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");for (String feature : features) { System.out.println(feature);}// Java 8之后:List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");features.forEach(n -> System.out.println(n));// 使用Java 8的方法引用更方便,方法引用由::双冒号操作符标示,// 看起来像C++的作用域解析运算符features.forEach(System.out::println);输出结果:LambdasDefault MethodStream APIDate and Time API
使用lambda表达式和函数式接口Predicate
除了在语言层面支持函数式编程风格,Java 8也添加了一个包,叫做 java.util.function。它包含了很多类,用来支持Java的函数式编程。其中一个便是Predicate,使用 java.util.function.Predicate 函数式接口以及lambda表达式,可以向API方法添加逻辑,用更少的代码支持更多的动态行为。下面是Java 8 Predicate 的例子,展示了过滤集合数据的多种常用方法。Predicate接口非常适用于做过滤。
public static void main(args[]){ List languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp"); System.out.println("Languages which starts with J :"); filter(languages, (str)->str.startsWith("J")); System.out.println("Languages which ends with a "); filter(languages, (str)->str.endsWith("a")); System.out.println("Print all languages :"); filter(languages, (str)->true); System.out.println("Print no language : "); filter(languages, (str)->false); System.out.println("Print language whose length greater than 4:"); filter(languages, (str)->str.length() > 4);}public static void filter(List names, Predicate condition) { for(String name: names) { if(condition.test(name)) { System.out.println(name + " "); } }}输出结果:Languages which starts with J :JavaLanguages which ends with aJavaScalaPrint all languages :JavaScalaC++HaskellLispPrint no language :Print language whose length greater than 4:ScalaHaskell// 更好的办法public static void filter(List names, Predicate condition) { names.stream().filter((name) -> (condition.test(name))).forEach((name) -> { System.out.println(name + " "); });}
如何在lambda表达式中加入Predicate
上个例子说到,java.util.function.Predicate 允许将两个或更多的 Predicate 合成一个。它提供类似于逻辑操作符AND和OR的方法,名字叫做and()、or()和xor(),用于将传入 filter() 方法的条件合并起来。例如,要得到所有以J开始,长度为四个字母的语言,可以定义两个独立的 Predicate 示例分别表示每一个条件,然后用 Predicate.and() 方法将它们合并起来,如下所示:
// 甚至可以用and()、or()和xor()逻辑函数来合并Predicate,// 例如要找到所有以J开始,长度为四个字母的名字,你可以合并两个Predicate并传入Predicate startsWithJ = (n) -> n.startsWith("J");Predicate fourLetterLong = (n) -> n.length() == 4;names.stream() .filter(startsWithJ.and(fourLetterLong)) .forEach((n) -> System.out.print("nName, which starts with 'J' and four letter long is : " + n));
…还有很多使用方法详细查看:Java8 lambda表达式10个示例
比较
既然lambda表达式即将正式取代Java代码中的匿名内部类,那么有必要对二者做一个比较分析。
第一个关键的不同点就是关键字 this。匿名类的 this 关键字指向匿名类,而lambda表达式的 this 关键字指向包围lambda表达式的类。
第二是编译方式。Java编译器将lambda表达式编译成类的私有方法。使用了Java 7的 invokedynamic 字节码指令来动态绑定这个方法。
参考:Android Studio 配置
jdk1.8新特性之lambda表达式及在Android Studio中的使用
Java8 lambda表达式10个示例
Java 8简明教程
更多相关文章
- Android 修改app图标和名称的方法
- 【Android】adapter has changed解决方法
- android中控件点击两次才响应onclick方法
- android彻底结束进程的两种方法
- android和html交互--动态注入方法
- Android方法数超出限定的问题(multiDex,jumboMode)
- Android原生方法和Web JS互相调用-两种写法
- android 访问网络不能在主线程中进行以及在线程中操作UI的解决方
- Android Studio——Android Studio更新升级方法