一说明

这边文章主要是带大家为什么会有lamda表达式的出现,流式思想的产生。具体的Lamda表达式操作,Stream流会在后面的文章更新,有兴趣的朋友也可以加一下我微信公众号,分享学习干货。

二java8核心

  1. Lamda表达式
  2. 流和默认方法
  3. 方法引用

三引子

3.1需求

现在有批车,是中国或者英国制造的,每辆车有不同的属性,现在根据客户不同的需求挑选车。

3.2建立车的实体类

/**
* @Author lsc
* @Description <p> </p>
* @Date 2019/9/27 11:09
* @Version 1.0
*/
@Data
@AllArgsConstructor
public class Car { // 车牌号
private String code;
// 颜色
private String color;
// 生产商
private String factory;
// 价格
private double price;
}

3.3 车辆初始化

    public List<Car> InitCar(){
ArrayList<Car> carList = new ArrayList<>();
Car car1 = new Car("100", "black", "中国", 20);
Car car2 = new Car("101", "gray", "中国", 30);
Car car3 = new Car("102", "yello", "中国", 50);
Car car4 = new Car("103", "silvery", "英国", 20);
Car car5 = new Car("104", "red", "英国", 30);
carList.add(car1);
carList.add(car2);
carList.add(car3);
carList.add(car4);
carList.add(car5);
return carList;
}

3.4 客户需求实现

1 现在客户需要看看价格大于20W的车,我们以前的思想应该就是写一个方法,筛选出价格大于20W的车,对于我们so easy 对不对。

    // 通过价格获取车
public List<Car> getCarByLowPrice(List<Car> carList){
ArrayList<Car> resultList = new ArrayList<>();
for (Car car : carList){
if (car.getPrice()>20){
resultList.add(car);
}
}
return resultList;
}

测试一下

    // 获取 车价格 20 W以上的车
@Test
public void getCarByLowPriceTest(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取价格20W以上的车
List<Car> carByPrice1 = carFunFactory.getCarByLowPrice(cars);
System.out.println(carByPrice1);
}

输出:

[Car(code=101, color=gray, factory=中国, price=30.0), Car(code=102, color=yello, factory=中国, price=50.0), Car(code=104, color=red, factory=英国, price=30.0)]

2 现在客户需求变更想看看30W以上的车,我们就copy一下代码改个数字对把

    // 通过价格获取车
public List<Car> getCarByHightPrice(List<Car> carList){
ArrayList<Car> resultList = new ArrayList<>();
for (Car car : carList){
if (car.getPrice()>30){
resultList.add(car);
}
}
return resultList;
}

测试:

    // 获取 车价格 30 W以上的车
@Test
public void getCarByHightPriceTest(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取价格30W以上的车
List<Car> carByPrice1 = carFunFactory.getCarByHightPrice(cars);
System.out.println(carByPrice1);
}

3 现在有稍微一点思想的程序员就知道copy代码就因为一行不同是不是太过了,这么多重复内容,没错这时我们就知道要把价格这个参数开出来。

    // 通过价格获取车
public List<Car> getCarByPrice(List<Car> carList,double price){
ArrayList<Car> resultList = new ArrayList<>();
for (Car car : carList){
if (car.getPrice()>price){
resultList.add(car);
}
}
return resultList;
}

测试:

    // 根据价格获取车
@Test
public void getCarByPriceTest(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取价格30W以上的车
List<Car> carByPrice1 = carFunFactory.getCarByPrice(cars,20);
List<Car> carByPrice2 = carFunFactory.getCarByPrice(cars,30);
System.out.println(carByPrice1);
System.out.println(carByPrice2);
}

4 现在又来一位新客户它想看银色的车并且价格高于30W,还是copy一下,然后我们的思维就是再开个参数对吧。

    // 通过颜色和价格获取车
public List<Car> getCarByColarAndPrce(List<Car> carList,String color,double price){
ArrayList<Car> resultList = new ArrayList<>();
for (Car car : carList){
if (color.equals(car.getColor())){
if (car.getPrice()>30){
resultList.add(car);
}
}
}
return resultList;
}

测试:

    // 根据颜色和价格获取车
@Test
public void getCarByColorAndPriceTest(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取颜色为黄色,价格大于30W的车
List<Car> carByPredicate = carFunFactory.getCarByColarAndPrce(cars,"yello",30);
//[Car(code=102, color=yello, factory=中国, price=50.0)]
System.out.println(carByPredicate);
}

四 问题

如果我的车属性非常多,现在根据客户需求不断的变更,我们开的参数也会越来越多,代码里面要套很多层if判断;如果又的客户不想看一些属性的车,那么我们就不得不再copy一个方法,然后在if判定,这样的结果就会产生很多重复代码(而且就因为那几个条件不同),代码冗余,可读性很差。针对这个问题我们开始了优化之旅

五优化

1 策略模式

针对copy代码冗余和客户行为需求不断变化的问题我们可以用策略模式进行优化。

先建个接口,然后我们实现这个接口,把策略写进实现类,客户需要不同的需求,我们就调用不同的策略。

车条件判断接口:

/**
* @Author lsc
* @Description <p> </p>
* @Date 2019/9/27 14:05
* @Version 1.0
*/
public interface CarPredicate { boolean test(Car car);
}

具体实现策略一:

/**
* @Author lsc
* @Description <p>筛选红色的车 </p>
* @Date 2019/9/27 14:08
* @Version 1.0
*/
public class CarPredicateByColor implements CarPredicate {
@Override
public boolean test(Car car) {
return "red".equals(car.getColor());
}
}

具体实现策略二:

/**
* @Author lsc
* @Description <p>获取车价格大于30W的车 </p>
* @Date 2019/9/27 14:06
* @Version 1.0
*/
public class CarPredicateByPrice implements CarPredicate {
@Override
public boolean test(Car car) {
return car.getPrice()>30;
}
}

测试根据不同的策略获取车:

    @Test
public void getCarByPredicatePrice(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取价格大于30为银色的车
// 实现将条件代码封装进对象传递入参
List<Car> carByPredicate = carFunFactory.getCarByPredicate(cars,new CarPredicateByPrice());
// [Car(code=102, color=yello, factory=中国, price=50.0)]
System.out.println(carByPredicate);
}
@Test
public void getCarByPredicateColor(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取颜色为红色的车
// 实现将条件代码封装进对象传递入参
List<Car> carByPredicate = carFunFactory.getCarByPredicate(cars,new CarPredicateByColor());
// [Car(code=104, color=red, factory=英国, price=30.0)]
System.out.println(carByPredicate);
}

 策略模式已经很好的解决了copy代码冗余的问题,但随着客户需要的不断变更,我们需要很多的实现类,感觉还是有点麻烦。

2 匿名类

针对客户需求不断变化我们使用策略模式要写很多实现类的问题,可以用匿名类解决。

	@Component
public class CarFunFactory {
// 新增通过函数式接口获得车辆
public List<Car> getCarByPredicate(List<Car> carList, CarPredicate carPredicate){
ArrayList<Car> resultList = new ArrayList<>();
for (Car car : carList){
if (carPredicate.test(car)){
resultList.add(car);
}
}
return resultList;
}
} @Test
public void getCarByPredicatByAnonymous(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取颜色为红色的车
List<Car> carByPrice1 = carFunFactory.getCarByPredicate(cars, new CarPredicate() {
@Override
public boolean test(Car car) {
return car.getPrice()>30;
}
});
// [Car(code=102, color=yello, factory=中国, price=50.0)]
System.out.println(carByPrice1);
}

3 Lamda表达式

 从当初的copy方法到策略模式,在到匿名内部类是不是已经简化了许多代码呢?答案是肯定的,但许多程序员包括我在内都不是很喜欢匿名类,因为它不易理解,还占用很多空间资源。于是Java8引入了Lamda表达式。

    public void getCarByPredicatByLamda(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取颜色为红色的车
List<Car> carByPrice1 = carFunFactory.getCarByPredicate(cars,car -> car.getPrice()>30);
// [Car(code=102, color=yello, factory=中国, price=50.0)]
System.out.println(carByPrice1);
}

这边讲解一下Lamda表示语法,具体内容在后面文章发布。

示例:car -> car.getPrice()>30

解析示例格式:

car 是参数列表;

-> 是箭头

car.getPrice()>30 是方法主体

Lamda语法格式:

  • 这是我们的简写模式(方法主体为一句表达式): (参数列表)-> 方法主体
  • 非简写模式:(参数列表)-> {方法主体;}

    说明:有时候无参那么就是 () -> 方法主体

4 Stream流

 有了Lamda表达式做优化已经非常简练直观,但java8还有个思想就是流式思想,其内置很多默认方法,省去了我们自己建立判断接口。

    @Test
public void getCarByPredicatByStream(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取颜色为红色的车
List<Car> collect = cars.stream().filter(car -> car.getPrice() > 30).collect(Collectors.toList());
// [Car(code=102, color=yello, factory=中国, price=50.0)]
System.out.println(collect);
}

六 再看看我们平时用到Lamda的例子

1排序

    // 匿名内部类方式对车编号进行排序
@Test
public void getCarSortByAnonymous(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取颜色为红色的车
cars.sort(new Comparator<Car>() {
@Override
public int compare(Car o1, Car o2) {
return o1.getCode().compareTo(o2.getCode());
}
});
System.out.println(cars);
}
// 使用 lamda表达式对车编码进行排序
@Test
public void getCarSortByLamda(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取颜色为红色的车
cars.sort((o1, o2) -> o1.getCode().compareTo(o2.getCode()));
System.out.println(cars);
}
// 使用 Stream API 对车编号进行排序
@Test
public void getCarSortByStream(){
// 初始化车信息
List<Car> cars = carFunFactory.InitCar();
// 获取颜色为红色的车
List<Car> collect = cars.stream().sorted((o1, o2) -> o1.getCode().compareTo(o2.getCode())).collect(Collectors.toList());
System.out.println(collect);
}

2 runnable

    @Test
public void runnableTest(){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello world youku1327");
}
});
thread.start();
}
@Test
public void runnableLamdaTest(){
Thread thread = new Thread(() -> System.out.println("hello world youku1327"));
thread.start(); }

七 总结

我们是将条件行为代码封装进了对象里面,然后将对象传递给特定的方法进行筛选出我们的需求,我们称这种操作为行为参数化

.
 之前的策略模式接口(CarPredicate)只有一个抽象方法,我们称这种接口为函数式接口,通常规范的函数式接口会带上@FunctionalInterface注解;


 java8还有个特性就是如果你的接口中没有抽象方法,但有个默认(default)方法,它也是函数式接口。


所有的匿名类实现方式我们都可以用Lamda表达式替换,Lamda表达式等于就是匿名类的简化。

八 致谢

作者坚持原创,分享干货技术,更新会有点慢;感谢观看我的文章,不足之处可以指出,如果想看更多好文章或者其他文章的源码可以关注我的微信公众号。

Java8-Lamda和Stream原理引入的更多相关文章

  1. 这可能是史上最好的 Java8 新特性 Stream 流教程

    本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...

  2. Java8 如何进行stream reduce,collection操作

    Java8 如何进行stream reduce,collection操作 2014-07-16 16:42 佚名 oschina 字号:T | T 在java8 JDK包含许多聚合操作(如平均值,总和 ...

  3. Java8 方式解决Stream流转其他数组

    Java8 方式解决Stream流转其他数组 一. 题记:原来的List转数组用的是如下方式: example private static void listToStringArray(List l ...

  4. java stream 原理

    java stream 原理 需求 从"Apple" "Bug" "ABC" "Dog"中选出以A开头的名字,然后从中选 ...

  5. Java8 新特性 Stream 非短路终端操作

    非短路终端操作 Java8 新特性 Stream 练习实例 非短路终端操作,就是所有的元素都遍厉完,直到最后才结束.用来收集成自己想要的数据. 方法有: 遍厉 forEach 归约 reduce 最大 ...

  6. Java8 新特性 Stream 短路终端操作

    短路终端操作 Java8 新特性 Stream 练习实例 传入一个谓词,返回传为boolean,如果符合条件,则直接结束流. 匹配所有 allMatch 任意匹配 anymMatch 不匹配 none ...

  7. Java8 新特性 Stream 无状态中间操作

    无状态中间操作 Java8 新特性 Stream 练习实例 中间无状态操作,可以在单个对单个的数据进行处理.比如:filter(过滤)一个元素的时候,也可以判断,比如map(映射)... 过滤 fil ...

  8. Java8 新特性 Stream() API

    新特性里面为什么要加入流Steam() 集合是Java中使用最多的API,几乎每一个Java程序都会制造和处理集合.集合对于很多程序都是必须的,但是如果一个集合进行,分组,排序,筛选,过滤...这些操 ...

  9. java8学习之Stream分组与分区详解

    Stream应用: 继续举例来操练Stream,对于下面这两个集合: 需求是:将这两个集合组合起来,形成对各自人员打招呼的结果,输出的结果如: "Hi zhangsan".&quo ...

随机推荐

  1. word使用指南(经常更新)

    一.快捷键 Ctrl+C 复制 Ctrl+X 剪切 Ctrl+V 粘贴 Ctrl+F 查找 Ctrl+A 全选 Ctrl+Z/Y 撤销/还原撤销 Ctrl+D 打开字体对话框 Ctrl+S 另存为 C ...

  2. Java 添加、读取、修改、删除Word文档属性

    Word文档属性包括常规.摘要.统计.内容.自定义等,其中摘要包括标题.主题.作者.经理.单位.类别.关键词.备注等项目,通过设置这些摘要信息或自定义属性可方便对文档的管理.本文中将主要介绍对文档摘要 ...

  3. odoo12 修行基础篇之 添加明细字段 (二)

    前一篇介绍了如何在视图和表单中添加字段.本节内容,我们讨论下如何在明细中加字段. 我想在销售页面明细中增加税额字段,这在表sale.order.line中已经存在,在此仅用来演示. odoo的明细一般 ...

  4. 新闻实时分析系统-Flume数据采集准备

    Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据:同时,Flume提供对数据进行简单处理,并 ...

  5. 记一次uboot中gunzip解压速度慢的问题排查

    背景 在项目中需要用到解压功能,之前还记录了下,将uboot解压代码移植到另外的bootloader中时,碰到的效率问题.最终查明是cache的配置导致的. https://www.cnblogs.c ...

  6. Flask 蓝图机制及应用

    我们都知道 flask 是一个轻量级的 web 框架,相对于其他同类型框架更为灵活.轻便.安全且容易上手.开发者可以随意编写自己想要的项目结构,同时还有很多的第三方库供君选择.但是灵活的同时也带来了相 ...

  7. 关于简单的Excel多页签底层导出_电子底账导出为例(.net core)

    [HttpPost] public ActionResult ExpEleAcc(string linknos) { string filenname = null; CommonResult< ...

  8. 华为OSPF与ACL综合应用

    一. 实验拓扑图 二.实验要求 1.企业内网运行OSPF路由协议,区域规划如图所示:2.财务和研发所在的区域不受其他区域链路不稳定性影响:3.AR1.AR2.AR3只允许被IT登录管理:4.YF和CW ...

  9. luogu P2759 奇怪的函数 |二分答案

    题目描述 使得 x^x达到或超过 n 位数字的最小正整数 x 是多少? 输入格式 一个正整数 n 输出格式 使得 x^x达到 n 位数字的最小正整数 x 计算一个数有多少位 log10(x)+1 #i ...

  10. AntV G2 图表tooltip重命名

    在做数据可视化的过程中,遇到了一个问题,就是给图表tooltip重命名. 在研究后,发现了三种方法: 方法1:一般情况下,可以在给chart绑定数据源时,添加scale配置,并在scale配置中设置别 ...