一直在看java并发的感觉说的有点多,就看点简单的放松一下吧!这次来简单说一下jdk8,很久没用,都陌生了,仔细看看还挺有意思的,让我们大脑转化一个角度来写代码;因为我们现在平常大部分用jdk7写代码,我们都是在想着这一步怎么做,下一步怎么做;而jdk8只需要知道这一步做什么,下一步做什么,思维的转换很有意思;

  首先说说什么叫做行为参数化?简单的来说就是传递的是一个行为,可以想象成传递一个lambda表达式,其中lambda表达式就不多说了;

  举个例子:

package com.example.demo.vo;

import lombok.Data;
import lombok.experimental.Accessors; @Data
@Accessors(chain = true)
public class Apple {
private String color;
private int weight; }

  假如一个集合中有很多苹果,我们首先要筛选出重量大于10的苹果,那么我们需要定义一个这样的方法:

static List<Apple> filterColor(List<Apple>inventory){
List<Apple> result = Lists.newArrayList();
for (Apple apple : inventory) {
if (apple.getWeight()>10) {
result.add(apple);
}
}
return result;
}

 

  如果有一天突然需求改变了,要求我们筛选出颜色为绿色的苹果,于是我们又要定义一个这样的方法:

static List<Apple> filterGreen(List<Apple>inventory){
List<Apple> result = Lists.newArrayList();
for (Apple apple : inventory) {
if (Objects.equal("green", apple.getColor())) {
result.add(apple);
}
}
return result;
}

 

  如果又有一天提了某某需求,于是吧啦吧啦,那么我们看看简单的看看这两个方法有什么不同啊,其实仔细一看,就是上面的for循环中if语句中筛选条件不一样,其他的代码直接复制粘贴的,我们知道复制粘贴有的时候太多了,你会看到很多重复的代码,这就很坑了,有没有比较简化一点的方法呢?

  其实很容易,既然上面其他部分都是一样的,我们把一样的部分提出来,当做一个模板,以后我们只需要传递我们定制的筛选条件不就行了吗?简单吧!那么问题又来了,怎么把那些代码编程一个模板呢?在jdk8中有一些函数式接口,其中一个就是Predicate,注解@FunctionalInterface翻译一下就是函数式接口嘛!我们暂时就用它的test方法,可以看到这个方法接收一个形参,返回一个boolean类型的,上面的代码中的筛选条件本质上就是接收一个Apple类型,返回一个boolean类型嘛!

  于是我们可以这样做制作一个模板出来:

static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
}

  那么问题又来了,制作出来了,怎么使用呢?我们就试试用上面的模板来筛选苹果重量和苹果颜色,这里会用到Lambda表达式:

    public static void main(String[] args) {
//用一个集合装三个苹果
List<Apple> apples = Lists.newArrayList();
Apple apple1 = new Apple();
apple1.setColor("red").setWeight(20);
Apple apple2 = new Apple();
apple2.setColor("green").setWeight(20);
Apple apple3 = new Apple();
apple3.setColor("black").setWeight(5);
apples.add(apple1);
apples.add(apple2);
apples.add(apple3); //筛选出重量>10的苹果,下面两种写法一样
// List<Apple> list1 = filterApples(apples,(Apple a)->a.getWeight()>10);
List<Apple> list1 = filterApples(apples,a->a.getWeight()>10);
System.out.println("重量大于10的苹果:"+list1); //筛选出颜色是绿色的苹果,下面两种写法一样
// List<Apple> list2 = filterApples(apples,(Apple a)->Objects.equal("green", a.getColor()));
List<Apple> list2 = filterApples(apples,a->Objects.equal("green", a.getColor()));
System.out.println("绿色苹果:"+list2); }

  到这里就行了么?还有更加有意思的就是流,流可以说是特地为了处理集合而创造的,其实上面的代码还是太麻烦了,还要自己定义一个方法,有没有更快更快的方法,下面是使用流的方式:

 //使用流筛选重量大于10的苹果
List<Apple> weightApples = apples.stream().filter(a->a.getWeight()>10).collect(Collectors.toList());
System.out.println(weightApples); //注意,每次获取流是一次性的,如果前面已经获取了流的返回值了,还想继续操作流,只能重新获取流;使用流筛选颜色是绿色的苹果
List<Apple> greenApples = apples.stream().filter(a->Objects.equal("green", a.getColor())).collect(Collectors.toList());
System.out.println(greenApples);

  看到没有,使用了流之后只需要几行代码,不用再定义什么方法了,只需要将集合变成一个流,然后链式调用filter方法,传进去一个行为(这里传的是一个Lambda表达式),然后再调用collect方法收集流中的元素;

  其实到这里还有没有可以优化的地方,当然有,就比如说每次都要System.out.println(xxx)方法真的很讨厌,能不能干掉,但是控制台却还是能打印出来,当然可以,这里就涉及到了一个概念叫做方法引用,什么叫做方法引用呢?即是一个函数指针,你可以这样想,当一个类被加载到jvm中了,那么我们只要知道这个类在哪个内存地址,就可以知道它的方法的内存地址了(可以想想调用静态方法的时候,直接用类名加方法名调用的),于是我们可以用这样的方式 类名::方法名 的方式调用某个方法,那么把System.out.println(xxx)修改一下就是System.out::printIn,代码修改如下,我们把两个集合分别遍历:

        //使用流筛选重量大于10的苹果
apples.stream().filter(a->a.getWeight()>10).collect(Collectors.toList()).forEach(System.out::println); //使用流筛选颜色是绿色的苹果
apples.stream().filter(a->Objects.equal("green", a.getColor())).collect(Collectors.toList()).forEach(System.out::println);

 

  上面的方法引用还只是最简单的方式,其他的后面有时间会慢慢说的;

  通过迅速的看了看jdk8,应该对这种集合形式的处理了解一些了,然后我们再分块讨论,比如Lambda表达式怎么写,函数式接口有哪些,流的操作有哪些,方法引用怎么使用等等!这些大概就涵盖了jdk8的80%了,后面还有jdk8新的日期和时间api,Optional代替null,默认方法等等就简单了;

迅速看一下jdk8的更多相关文章

  1. 看不懂JDK8的流操作?5分钟带你入门(转)

    在JDK1.8里有两个非常高级的新操作,它们分别是:Lambda 表达式和 Stream 流. Lambda表达式 让我们先说说 Lambda 表达式吧,这个表达式最大的作用就是简化语法,让代码更加易 ...

  2. 谈谈HashMap与HashTable

    谈谈HashMap与HashTable HashMap 我们一直知道HashMap是非线程安全的,HashTable是线程安全的,可这是为什么呢?先聊聊HashMap吧,想要了解它为什么是非线程安全的 ...

  3. Java中常见数据结构Map之HashMap

    之前很早就在博客中写过HashMap的一些东西: 彻底搞懂HashMap,HashTableConcurrentHashMap关联: http://www.cnblogs.com/wang-meng/ ...

  4. HashMap中的hash算法总结

    前言 算法一直是我的弱项,然而面试中基本是必考的项目,刚好上次看到一个HashMap的面试题,今天也来学习下 HashMap中的hash算法是如何实现的. 数学知识回顾 << : 左移运算 ...

  5. Integer代码分析

    我们都知道Integer是int的封装类,提供了一些类型转换等工具方法,有一个-128-127的缓存,而且是final的. ----------------------------- 干货: Inte ...

  6. Node.js 网页爬虫再进阶,cheerio助力

    任务还是读取博文标题. 读取app2.js // 内置http模块,提供了http服务器和客户端功能 var http=require("http"); // cheerio模块, ...

  7. JDK1.7中HashMap死环问题及JDK1.8中对HashMap的优化源码详解

    一.JDK1.7中HashMap扩容死锁问题 我们首先来看一下JDK1.7中put方法的源码 我们打开addEntry方法如下,它会判断数组当前容量是否已经超过的阈值,例如假设当前的数组容量是16,加 ...

  8. 面试题-关于Java线程池一篇文章就够了

    在Java面试中,线程池相关知识,虽不能说是必问提,但出现的频次也是非常高的.同时又鉴于公众号"程序新视界"的读者后台留言让写一篇关于Java线程池的文章,于是就有本篇内容,本篇将 ...

  9. 使用Intellij idea新建Java Web项目(servlet) 原理及初步使用

    准备 JDK       (配置JDK_HOME\bin   和 CLASSPATH)   注:JDK8下载已经需要注册了,请使用JDK11(现在是官方长期支持的版本)     对于我们新手来说,JD ...

随机推荐

  1. sencha Architect 3.2及以下版本都适用的 破解方法

    找到 没有的话 打开隐藏文件夹 C:\Users\ll\AppData\Local\Sencha\Sencha Architect 3.2 用编辑器 打开user.license 把 Print 修改 ...

  2. OpenGL 编程指南 (3.2)

    1.帧缓冲对象 帧缓冲对象对于离屏渲染.纹理贴图更新.缓存乒乓技术(buffer ping-pongqing,GPGPU的一种数据传输方式)的实现意义非凡,它减少了大量的数据拷贝工作. 建立帧缓冲需要 ...

  3. 常用的 19 条 MySQL 优化

    一.EXPLAIN 做MySQL优化,我们要善用 EXPLAIN 查看SQL执行计划. 下面来个简单的示例,标注(1,2,3,4,5)我们要重点关注的数据 type列,连接类型.一个好的sql语句至少 ...

  4. Date、DateFormat、Calendar、Math、System

    Date(基本已过时了,被Calendar替换) 构造方法(有两个) Date(); Date(long l);long类型的毫秒值 常用方法(其他方法都已被Calendar替换) getTime() ...

  5. java的并发

    问题: 过程: 正常流程:记录生成:状态=1-->北京:状态 = 3,4,-->定时任务:状态=5--->结束 异常流程:一条待处理的的记录生成以后,马上被定时任务处理,加载到内存, ...

  6. Python与C语言基础对比(Python快速入门)

    代码较长,建议使用电脑阅读本文. 10分钟入门Python 本文中使用的是Python3 如果你曾经学过C语言,阅读此文,相信你能迅速发现这两种语言的异同,达到快速入门的目的.下面将开始介绍它们的异同 ...

  7. C++-POJ3274-Gold Balanced Lineup[hash]

    不是很懂? 胡乱hash #include <set> #include <map> #include <cmath> #include <queue> ...

  8. lua 随机数 math.random()和math.randomseed()用法

    用法一:  不给范围,就随机算一个0~1之间的小数: 用法二:给一个参数,就取1~n之间的随机数 用法三:给两个参数,就取m~n之间的随机数 math.randomseed()用法:     由于C中 ...

  9. Go反射

    一.引入 不同语言的反射模型不尽相同,有些语言还不支持反射.<Go 语言圣经>中是这样定义反射的: Go 语言提供了一种机制在运行时更新变量和检查它们的值.调用它们的方法,但是在编译时并不 ...

  10. 每天进步一点点------Xilinx FPGA开发工具 EDK SDK术语

    XPS:Xilinx Platform Studio,平台工作室.用于嵌入式处理器硬件部分的开发. SDK:Software Development Kit,软件开发套件.基于Eclipse平台,支持 ...