java8的lamda的意义,java8之Lambda知识回顾

前提

18年第一篇文章,祝各位新年快乐哈~

介绍Lambda之前,可以看下我们定义View点击事件的一般做法

1. new View(this).setOnClickListener(new View.OnClickListener() {

2. @Override

3. public void onClick(View view) {

4. //...

5. }

6. });

这种回调模式在日常开发中很常见,但是随之也暴露了一些不良的弊端

1、非抽象化,整个代码有五行,其实实际逻辑只有在onclick里面,其他并不关心

2、无法使用外部非final属性(这个遇到最多了)

3、this指针意义不明确

4、等等

所以,java8特性Lambda正好解决了这一系列问题,以下

new View(this).setOnClickListener(view->{

//.. doing

});

1.引入的lambda

lambda是在java8引入的函数表达式,其实是一种匿名的表达方式,Lambda表达式语法由参数列表、->和函数体组成。函数体既可以是一个表达式也可以是一个代码块。

例如以下

# 表达式

()->8; // 这里8是return的返回结果,简化了return

#代码块

()->{

//... 函数体

}

2.案例

说多不如做多,现在举个🌰

2.1 线程利用lambada表达式

new Thread(()->{

//这里是线程运行的区域,实质是抽象化了Runnable的run方法

Log.i(TAG,"Thread is running...");

}).run();

2.2 多种情况利用lambada表达式

首先定义一个测试回调接口类

/**

* 这个类完全提供一些接口测试

*/

static class LambdaProvider{

TestInterface0 mTestInterface0; // 测试不带参数与不带返回值

TestInterface1 mTestInterface1;// 测试带返回值

TestInterface2 mTestInterface2;// 测试待返回值、带参数

TestInterface3 mTestInterface3;//测试抛出异常方法

public void setmTestInterface0(TestInterface0 mTestInterface0) {

this.mTestInterface0 = mTestInterface0;

}

public void setmTestInterface1(TestInterface1 mTestInterface1) {

this.mTestInterface1 = mTestInterface1;

}

public void setmTestInterface2(TestInterface2 mTestInterface2) {

this.mTestInterface2 = mTestInterface2;

}

public void setmTestInterface3(TestInterface3 mTestInterface3) {

this.mTestInterface3 = mTestInterface3;

}

public interface TestInterface0{

// 不带参数、不带返回值

public void method();

}

public interface TestInterface1{

// 带返回值

public int method1();

}

public interface TestInterface2{

// 带参数

public int method2(int x);

}

public interface TestInterface3{

// 抛出异常方法

public void method3() throws Exception;

}

}

测试代码

String value="";

LambdaProvider mLambdaProvider = new LambdaProvider();

mLambdaProvider.setmTestInterface1(()->2); // 直接返回2

mLambdaProvider.setmTestInterface1(()-> 2+4 ); // 直接返回计算表达式

mLambdaProvider.setmTestInterface1(()->{ // 直接返回作用域

Log.i(TAG,"setmTestInterface1 here...");

//... do something

String str = value; // 不用final就可以访问到了

this.demo(); // this指针不再模糊

return 3;

});

// # 3 针对参数+返回值利用lambada表达式

mLambdaProvider.setmTestInterface2((x)->2); // 直接返回2

mLambdaProvider.setmTestInterface2((x)-> 2+4 ); //x 直接返回计算表达式

mLambdaProvider.setmTestInterface2((x)->{ // 使用形参x计算后返回

return x+2+4;

});

// #4 针对会抛出异常

mLambdaProvider.setmTestInterface3(()->{

throw new IllegalStateException("hi~");

});

3.高效的 Stream api

如果应用最小支持sdk24以上,Stream是非常高效的事情。当然国内sdk24以上的并不是占绝大多数,但是我们也可以先了解高效的Stream。

先小试牛刀,一般foreach遍历list,我们一般会这么做

List listSteam = Arrays.asList("0","1","2");

for (String i:listSteam){

//...

}

利用steam api,我们可以这么做

listSteam.forEach(i->{

//...

});

反正我是佩服的😢

什么是Stream?

借鉴某大神的说明,“Stream不是集合元素,它也不是数据结构、不能保存数据,它更像一个更高级的Interator。Stream提供了强大的数据集合操作功能,并被深入整合到现有的集合类和其它的JDK类型中。流的操作可以被组合成流水线(Pipeline)”

使用Stream可以做很多事情,如果以后会接触到rxjava,你会发现很多操作符是借鉴了Stream里面流的概念。在Stream操作中,都会涉及一个步骤

上流(Stream)->处理->下流结果(Stream)

举个例子🌰

首先创建一个测试model,并且实例了一个数组

class Model{

public String type;//"1","2" 用于区别类型

public String name;

public Model(String type, String name) {

this.type = type;

this.name = name;

}

@Override

public String toString() {

return "Model (type: " + type +" name: "+name+")";

}

}

List listSteam = Arrays.asList(new LambdaProvider.Model("1","siven0"),

new LambdaProvider.Model("2","siven1"),new LambdaProvider.Model("2","siven2")

,new LambdaProvider.Model("2","siven3"));

场景1:

只提取type是2的数据到新数组

List newList = listSteam.stream()

.filter(s->s.type.equals("2"))

.collect(Collectors.toList());

newList.forEach(s-> consoleInput(TAG,"stream newList: "+s));

Collectors是负责接收上面传递过来的流,tolist是将传递过来的流重新组合成list

filter是负责过滤上面传递过来的流,里面return是一个布尔值

场景2:

提取ype是2的数据,并且将流转化为其他数据的流后组成新的数组

List listIndex = listSteam.stream()

.filter(s->s.type.equals("2"))

.map(s->s.name)

.collect(Collectors.toList());

listIndex.stream().forEach(s-> consoleInput(TAG,"stream listIndex: "+s));

map组要做流转化,上面的场景是接收到Model的流后,通过访问实体的对象name转化为字符串流(下面用map我会贴更加详细的说明)

map的各种玩法(建议阅读):

// 玩玩map转化

List stringList = Arrays.asList("1","2","3"); // 随便申请一个list

consoleInput(TAG,"玩玩map转化 ----- flatmap ");

List tmp0 = stringList.stream()

.flatMap((s)->{

String str = (String) s + " - 转化(flatmap)";

consoleInput(TAG,"转化前 "+s + ",转化后 " + str);

List result = new ArrayList<>();

result.add(str);

return result.stream();

})

// 为了方便读者阅读,我用非lambda表达式

// .flatMap(new Function>() {

// @Override

// public Stream apply(String s) {

// String str = (String) s + " - 转化";

// consoleInput(TAG,"转化前 "+s + "转化后 " + str);

// List result = new ArrayList<>();

// result.add(str);

// return result.stream();

// }

// })

.collect(Collectors.toList());// 流收集起来

consoleInput(TAG,"转换后结果输出 ");

tmp0.stream().forEach(c->consoleInput(TAG,"-> "+c));

consoleInput(TAG,"玩玩map转化 ----- map ");

tmp0 = stringList.stream()

.map((s)->{

String str = (String) s + " - 转化(map)";

consoleInput(TAG,"转化前 "+s + ",转化后 " + str);

return str;

})

// 为了方便读者阅读,我用非lambda表达式

// .map(new Function() {

// @Override

// public String apply(String s) {

// String str = (String) s + " - 转化(map)";

// consoleInput(TAG,"转化前 "+s + ",转化后 " + str);

// return str; }

// })

.collect(Collectors.toList());// 收集

consoleInput(TAG,"转换后结果输出 ");

tmp0.stream().forEach(c->consoleInput(TAG,"-> "+c));

consoleInput(TAG,"玩玩map转化 ----- sum ");

int sum = stringList.stream()

.mapToInt(s->Integer.valueOf(s)) // map转int

.sorted() // 排序

.sum();

consoleInput(TAG,"转换后结果输出 "+sum);

这里要思考的就是flatMap与map有什么区别了,从方法看flatMap是object->stream。而map是object->object。如果你的场景是希望自己的上流传递有多次处理逻辑,并不希望马上得到下流的结果。那flatMap更满足你需求了。如果是直接A到B,明确的结果,map也许更适合你

4.总结

年终了~祝大家工作顺利,事业进步!

by siven

2018.1.5

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值