传统的的Java 集合操作是有些啰嗦的,当我们需要对结合元素进行过滤,排序等操作的时候,通常需要写好几行代码以及定义临时变量。

而Java8 Stream API 可以极大简化这一操作,代码行数少,且易读。

我们以“找女朋友”为例来看看Java8的Stream API相比传统写法有多香。假设我们定义了一个女朋友类,具有几个关键的指标:姓名,身高,体重,颜值。如下所示:

class Girl {
private String name;
private int height;
private int weight;
private int score;
// 省略get,set及hashCode等方法
}

我们有一批适龄女青年名单,如下:

public static List<Girl> initGirlList(){
List<Girl> result = new ArrayList<>();
result.add(new Girl("赵小花",170,60,6));
result.add(new Girl("钱小花",171,62,7));
result.add(new Girl("孙小花",172,59,8));
// 省略....
return result;
}

心仪女朋友的筛选条件

假设心仪的女朋友是:体重,身高适中,颜值越高越好。本次设置的条件是找出:身高>=162 并且 体重<=53的女孩,然后按颜值排序前三名。

Java7的写法

数据去重

由于数据可能有重复,这会干扰我们的筛选,因此,第一步先去掉重复数据。代码如下:

List<Girl> girlList = initGirlList();// 初始化一批数据
// 数据去重
List<Girl> distinctGirl = new ArrayList<>();
for (Girl g: girlList){
if(!distinctGirl.contains(g)){
distinctGirl.add(g);
}
}

这里new了一个新的distinctGirl来存放去重之后的数据,代码很简单,没啥可说的。

筛选数据

下面我们要去掉不合格的数据,本次筛选条件是身高>=162 并且 体重<=53,代码如下:

// 过滤身高,体重不符合的
List<Girl> girlTemp = new ArrayList<>();
for(Girl g: distinctGirl){
if(g.getHeight() >= 162 && g.getWeight() <= 53){
girlTemp.add(g);
}
}

这里运用上一步中去重之后的distinctGirl,遍历,并将符合条件的放入新的list girlTemp,这里又创建了一个中间list。

数据排序

经过上面啰嗦的两步,我们得到了符合我们要求的数据,现在我们需要根据颜值高低进行排名,代码如下:

Collections.sort(girlTemp, new Comparator<Girl>() {
@Override
public int compare(Girl g1, Girl g2) {
BigDecimal score1 = new BigDecimal(g1.getScore());
BigDecimal score2 = new BigDecimal(g2.getScore());
return score2.subtract(score1).intValue();
}
});

这里使用了Collections工具类的sort方法,传递了一个匿名类,并在其compare方法中实现了排序的逻辑,这依然是传统集合排序的操作。

输出结果

经过上面的几步传统的Java集合操作,我们终于得到了想要的数据。现在我们要输出前三名。

int i = 1;
for (Girl g : girlTemp) {
if(i>=3){
break;
}
System.out.println(g.toString());
}

OK,至此我们的程序输出了筛选的结果。上面的写法,貌似逻辑很清晰,一步步徐徐渐进。是的,这种传统的写法,Java程序员们已经乐呵呵的写了很多年了。

一看这个代码足足有20多行!可是实现的逻辑并没有太复杂啊?过阵子你回头看这个代码的话,你多半忘记了这么一大段代码是干嘛的。如果有注释还好,你大概扫一一眼能帮助你快速理清代码做了啥。如果没有注释,你需要逐行去读完这20多行代码,才能明白其逻辑。

Java8 Stream API的写法

这里我们在回顾一下,我们的目标:从一个girlList中找出:身高>=162 并且 体重<=53的女孩,然后按颜值排序前三名。Java8的代码如下:

List<Girl> girlList = initGirlList();
girlList.stream()
.filter( g -> g.getHeight() >= 162 && g.getWeight() <= 53)
.distinct()
.sorted(Comparator.comparing(Girl::getScore).reversed())
.limit(3)
.forEach( g -> System.out.println(g.toString()));

代码6行!并且即使不了解Stream API,且你第一次看这个代码也能猜出是什么意思,filter-过滤,distinct-去重,sort-排序,limit-限制条数,forEach-遍历,就这么简单。

结语

Java 这么老语言,如今都Java13了,然而,最具影响的版本我认为还是Java8。我上学那会儿,学校用Java6的写法教学。工作之后开始写Java7的try-with-resource、钻石语法等。一直到现在,市面上很多项目都是Java7。有一次有同事给我说他在前公司写Java8被项目经理说了一顿,我问为啥。他说因为项目经理认为写Java7好维护,团队人人都会写Java7,写Java8的人不多……无语凝噎。

如果你还没用上Java8,但愿本文中的小例子已经成功的勾起了你用上Java8的兴致。问卷:你现在使用的版本是多少?

评论下面附了完整源码



推荐阅读

Java8系列- 何用Java8 Stream API进行数据抽取与收集

SpringMVC是怎么工作的,SpringMVC的工作原理

Mybatis Mapper接口是如何找到实现类的-源码分析

小程序云开发:菜鸟也能全栈做产品

CORS详解,CORS原理分析

工作6年,失业19天

Docker & k8s 系列一:快速上手docker

Docker & k8s 系列二:本机k8s环境搭建

Docker & k8s 系列三:在k8s中部署单个服务实例

如何用Java8 Stream API找到心仪的女朋友的更多相关文章

  1. 何用Java8 Stream API进行数据抽取与收集

    上一篇中我们通过一个实例看到了Java8 Stream API 相较于传统的的Java 集合操作的简洁与优势,本篇我们依然借助于一个实际的例子来看看Java8 Stream API 如何抽取及收集数据 ...

  2. 使用Java8 Stream API对Map按键或值进行排序

    一.什么是Java 8 Stream 使用Java 8 Streams,我们可以按键和按值对映射进行排序.下面是它的工作原理: 将Map或List等集合类对象转换为Stream对象 使用Streams ...

  3. Fork/Join框架与Java8 Stream API 之并行流的速度比较

    Fork/Join 框架有特定的ExecutorService和线程池构成.ExecutorService可以运行任务,并且这个任务会被分解成较小的任务,它们从线程池中被fork(被不同的线程执行)出 ...

  4. Java8 Stream API

    Stream是Java8中,操作集合的一个重要特性. 从iteration到Stream操作 当你操作一个集合的时候,你通常的做法是迭代每一个元素,然后处理你想要的事情.举个例子: String co ...

  5. JAVA8 Stream API的使用

    /** * @auther hhh * @date 2018/12/31 12:48 * @description Stream流:用来处理数组.集合的API * 1.不是数据结构,没有内部存储(只是 ...

  6. java8 stream api流式编程

    java8自带常用的函数式接口 Predicate boolean test(T t) 传入一个参数返回boolean值 Consumer void accept(T t) 传入一个参数,无返回值 F ...

  7. 1.分类维护-通过Java8 Stream API 获取商品三级分类数据

    实体类 @Data @TableName("pms_category") public class CategoryEntity implements Serializable { ...

  8. java8 Stream API笔记

    生成Stream Source的方式 从Collection和数组生成 * Collection.stream() * Collection.parallelStream() * Arrays.str ...

  9. 【Java8新特性】面试官:谈谈Java8中的Stream API有哪些终止操作?

    写在前面 如果你出去面试,面试官问了你关于Java8 Stream API的一些问题,比如:Java8中创建Stream流有哪几种方式?(可以参见:<[Java8新特性]面试官问我:Java8中 ...

随机推荐

  1. 5.基本的Dos命令

    打开cmd的方式: 开始+系统+命令提示符 win+r 输入cmd 在任意文件夹下面,按住shift+鼠标右键点击,在此处打开命令行窗口 在资源管理器(win+E)的地址栏前面加上cmd 路径 管理员 ...

  2. GStreamer基础教程13 - 调试Pipeline

    摘要 在很多情况下,我们需要对GStreamer创建的Pipeline进行调试,来了解其运行机制以解决所遇到的问题.为此,GStreamer提供了相应的调试机制,方便我们快速定位问题. 查看调试日志 ...

  3. AttributeError: 'Table' object has no attribute 'plot'错误

    今天在用到camelot爬取pdf的表格时,想选取部分区域进行爬取,就想用plot把pdf画一下,选个坐标. 看了网上的示例,在使用camelot.read_pdf获取当前页面以后调用tables[0 ...

  4. Python读取字典(Dictionary)内数据的方法

    读取json后,数据类型为字典,对字典内数据的提取又有不同的方法,根据不同的字典类型 上图可以看到有”[]”,”{}” python语言最常见的括号有三种,分别是:小括号( ).中括号[ ]和大括号也 ...

  5. 请求参content-type的值为json,返回报错的解决方法

    如上图,请求后报参数错误 原因content-type的值为json requests.post左侧的data要改为json 即r = requests.post(url, json=data, he ...

  6. 机器学习-TensorFlow应用之classification和ROC curve

    概述 前面几节讲的是linear regression的内容,这里咱们再讲一个非常常用的一种模型那就是classification,classification顾名思义就是分类的意思,在实际的情况是非 ...

  7. 简单实现Android手机“全局可调试”(ro.debuggable = 1)的方法【锤子坚果3】

    在Android真机上调试程序有一个前提,就是这个apk包必须有 debuggable=true 的属性才行.而除了自己开发的apk能够控制打包属性之外,其他的程序发行之后显然不会设这个值为 true ...

  8. Can you answer these queries III(线段树)

    Can you answer these queries III(luogu) Description 维护一个长度为n的序列A,进行q次询问或操作 0 x y:把Ax改为y 1 x y:询问区间[l ...

  9. Oracle监听器

    Oracle 监听器 Listener 是一个重要的数据库服务器组件,在整个 Oracle 体系结构中,扮演着重要的作用.它负责管理 Oracle 数据库和客户端之间的通讯,它在一个特定的网卡端口(默 ...

  10. 面试总结 | Linux后台开发不得不看的知识点(给进军bat的你!)

    目录 一 自我介绍 二 面试情况 三 相关知识点汇总 1 c/c++相关 2 计算机网络 3 数据结构相关 4 数据库相关 5 操作系统 6 Linux基础知识及应用编程(后台必备!) 7 大数问题 ...