JAVA8初探-让方法参数具备行为能力并引入Lambda表达式
关于JAVA8学习的意义先来贴一下某网站上的对它的简单介绍:“Java 8可谓Java语言历史上变化最大的一个版本,其承诺要调整Java编程向着函数式风格迈进,这有助于编写出更为简洁、表达力更强,并且在很多情况下能够利用并行硬件的代码。Java 8所带来的函数式编程特性使得Java从此屹立于函数式编程的世界,这是Java这门“古老的”编程语言自从发布以来变化最大的一个版本,在很多地方从根本上改变了我们编码的方式,使得Java也可以像Scala、Python、JavaScript等函数式编程语言一样通过更为精炼、表现力更强的函数式编程手法来编写代码。我认为,Java 8作为Java历史上变化最为激进的一个版本,值得每一个有志向的Java开发者好好研究并落实到自己的日常编码工作中。”,而其实在实际工作中基本上本地的JDK环境都已经升级到了JAVA8版本了,但是!!确对JAVA8中的东东一点都不了解,当然也谈不上去在实际工作中去使用JAVA8的东东,基本还是用JDK5那些标准的API去写代码,既然都已经是JAVA8环境了,而且又有这么大的变化,为何不拥抱一下它使之可以为我们实际工作所用呢,所以接下来慢慢来学习使用它。
在学习之前,先介绍一本很好的JAVA8的教程:Java 8 in Action,如下:
而学习以它为向导一点点去学,打开目录可以看到:
而从第二章开始学,也就是这次要学的:Passing code with behavior parameterization 【让方法参数具备行为能力】
下面就用代码来进行参考学习,开发工具这里不用eclipse,而是用intellij idea,因为我们的Android Studio也是来自于它,而intellij idea是专为JAVA而生的,也是被如今广泛使用的,顺便也享用一下它的开发体验,首先先去官网下载:https://www.jetbrains.com/:
貌似当时学习kotlin也是上了这个官网,点击进去之后就可以到下载页面了:
看一下这两个版本的区别:
可见旗舰版功能是最多最全的,但是是收费滴,不过貌似网上有一些破解教程【http://blog.csdn.net/nishiwodebocai21/article/details/71359619,其中我试用了博客中的方法一】,具体安装这里就不多说了,安装好之后,新建工程:
然后按操作进行创建项目既可,创建一个空项目之后的目录如下:
接下来就可以正式编写我们的代码了,还是按java8 in action的书上的例子来,如书上开篇所说:
然后书上就以"在农厂工作,需要对水果进行过滤统计,并且怎么很轻松的应对农场主给出的各种不同的统计需求"为例,下面就围绕着书的例子一步步的来引起JAVA8的东东,如下:
所以下面自己动手照着来做一下,光看不练假把式,所以新建一个Apple类:
/**
* 苹果实体
*/
public class Apple {
private String color;
private long weight; public Apple(String color, long weight) {
this.color = color;
this.weight = weight;
} public String getColor() {
return color;
} public void setColor(String color) {
this.color = color;
} public long getWeight() {
return weight;
} public void setWeight(long weight) {
this.weight = weight;
} @Override
public String toString() {
return "Apple{" +
"color='" + color + '\'' +
", weight=" + weight +
'}';
}
}
再来建一个类用来实现苹果的筛选,比较简单直接给出,不多解释:
/**
* 苹果的筛选
*/
public class FilterApple { public static List<Apple> filterGreenApples(List<Apple> apples) {
List<Apple> result = new ArrayList<>();
for (Apple apple : apples) {
if ("green".equals(apple.getColor()))
result.add(apple);
}
return result;
} public static void main(String[] args) {
List<Apple> apples = Arrays.asList(new Apple("green", 150),
new Apple("yellow", 120),
new Apple("green", 170));
List<Apple> greenApples = filterGreenApples(apples); System.out.println(greenApples);
}
}
编译运行:
这种无脑的代码不用去在意其实现,而在于推导JAVA8东东的过程,所以继续:这时农场主又来新需求了,需要筛选出红颜色的苹果,怎么做呢?
如果不用大脑想的方式则再写一个找红苹果的方法既可,伪代码类似于:
但是显然这种方式应对万变的需求不是特别好,如果还要找其它条件的苹果那还得不断增加方法,比如灵活的方式应该如书中所提到:
所以修改我们的代码如下:
编译运行:
那此时农场主要提需求了:"筛选出重量在150g以上的所有苹果",那怎么实现这种需求呢?简单,再搞个方法不就得了,如书中所示:
但是这时农场主的需求又变了:"找出在150g以上的所有红色的苹果",也就是条件既有重量,也有颜色,那这时我们代码又可以修改为:
很明显面对农场主的这些需求目前的这种代码实现方式应对有点吃力了,那有没有一种更加幽雅更加灵活的实现方式呢?当然有:利用策略模式实现,书中也提到了,这里就不贴书上的例子了,直接写我们的代码:
编译运行:
如果是其它条件则新建子类去继承接口去定义就好了,但是!!书中作者说这种方式不太好,代码量大,而且不够简洁,要更简洁其实用匿名内部类的写法可能更加精练,如书中所说:
但是书中又谈到了使用匿名类部类的不好:占空间、代码容易混淆:
但是,其实还有一个重要为啥要使用Lambda表达式的原因就是: 使用Lambda表达式会比使用上面匿名内部类或子类继承的方式更节省空间,因为java8在JVM上的空间是发生了具体在变化的,如何可以证明呢?下面用jdk自带的jstat命令去查看一下JVM的内存结构,对比一下java7和java8之间的区别,具体如下:
先查看一下JAVA7的JVM结构:
再查看一下JAVA8的JVM结构:
对比一下:
貌似上面的对比也体会不到使用Lambda表达式的代码更省空间呀,这时JAVA8的开篇暂且放一放它的研究,总之为啥要引入Lambda表达式有个重要原因就是:更省空间!
【提示】:Jstat是JDK自带的一个轻量级小工具。全称“Java Virtual Machine statistics monitoring tool”,它位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。关于这些命令先不用太过纠结,等未来有时间再来探究下,目前主要是通过这个实验来感性的认知一下JAVA8上内存结构是发生了变化,并且使用Lambda表达式会更省空间就足够了。
那既然已经引入了Lambda表达式了,那倒底这长啥样呢?下面初步去使用下它,还是以之前的苹果的过滤的小案列去使用,如下:
/**
* 苹果的筛选
*/
public class FilterApple { public interface AppleFilter {
boolean filter(Apple apple);
} //比如要找出大于150g的所有绿苹果,定义一个相应的策略
public static class GreenAnd150WeightFilter implements AppleFilter { @Override
public boolean filter(Apple apple) {
return "green".equals(apple.getColor()) && apple.getWeight() > 150;
}
} public static List<Apple> filterApples(List<Apple> apples, AppleFilter appleFilter) {
List<Apple> result = new ArrayList<>();
for (Apple apple : apples) {
if (appleFilter.filter(apple))
result.add(apple);
}
return result;
} public static void main(String[] args) {
List<Apple> apples = Arrays.asList(new Apple("green", 150),
new Apple("yellow", 120),
new Apple("green", 170));
List<Apple> greenApples = filterApples(apples, new GreenAnd150WeightFilter());
System.out.println(greenApples);
}
}
下面开始,首先先介绍一个JAVA8的概念:就是在一个接口中如果只有一个方法,其实就是一个Functional,这时就可以用Annotation来标注它:
也就是说它就可以用Lambda表达式去作业的,这里就用Lambda表达式来查询所有绿颜色的苹果,如下:
编译运行:
语法是不是比较奇怪,等于第一个括号里的是接口方法中的参数,其实还可以简化:
另外还可以简化:
而细心观察一下IDE,左侧有个提示:
再回到我们的接口,在阐述使用Lambda表达式时说到只有当接口中只有一个方法时才是用Lambda表达式可以对它进行作业的,那如果我再声明一个方法会怎样?
所以说@FunctionalInterface这个注解是说明该接口是Functional的,可以使用Lambda表达式去使用它,另外难道只有存在一个方法的接口才能使用这个注解么?其实不然,default的方法和static方法也可以定义在这个接口中,如下:
【注意】:居然在JAVA8中可以在一个接口中定义static和default的方法实现,好强大,貌似以前版本的接口只能有声明~
另外,对于一个具有Functional的接口如果不写这个Annotation也是可以的,只是代码可读性上没有加上好。
其实对于JDK8中的一些系统类也有声明成Functional的,这里以线程中的Runnable接口为例,看下它在JAVA8中的原码:
所以说可以有Lambda表达式来写写我们的线程代码,说干就干,先用传统的方式来启动一个线程:
那如果用Lambda如何写呢?
编译运行:
是不是Lambda表达式写起来更加简洁,语法上可能是有些怪异,肯定是有一个熟悉适应的过程,其实对于之前我们JDK中使用的一些系统接口很多都加上了Functional的行为,再看一个:
所以Lambda表达式是java8的很重要的特性,这片是初步先感受了下它的神奇,接下来会仔细一点点去深入的,加油!
JAVA8初探-让方法参数具备行为能力并引入Lambda表达式的更多相关文章
- 【Java8新特性】你知道Java8为什么要引入Lambda表达式吗?
写在前面 这是一道真实的面试题,一个读者朋友出去面试,面试官竟然问他这样一个问题:你说说Java8中为什么引入Lambda表达式?引入Lambda表达式后有哪些好处呢?还好这个朋友对Java8早有准备 ...
- [二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口
函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type use ...
- Java8中的[方法引用]“双冒号”——走进Java Lambda(四)
前面的章节我们提及到过双冒号运算符,双冒号运算就是Java中的[方法引用],[方法引用]的格式是 类名::方法名 注意是方法名哦,后面没有括号“()”哒.为啥不要括号,因为这样的是式子并不代表一定会调 ...
- .net学习之新语法学习(匿名类和匿名方法,扩展方法,系统内置委托,Lambda表达式和linq等)
1.自动属性 Auto-Implemented Properties 2.隐式类型 var var变量不能作为全局变量使用,因为不能在编译时确定类型 3.参数默认值 和 命名参数 4.对象初始化器 ...
- Ext.ux.grid.feature.Searching 解析查询参数,动态产生linq lambda表达式
上篇文章中http://www.cnblogs.com/qidian10/p/3209439.html我们介绍了如何使用Grid的查询组建,而且将查询的参数传递到了后台. 那么我们后台如何介绍参数,并 ...
- java8 探讨与分析匿名内部类、lambda表达式、方法引用的底层实现
问题解决思路:查看编译生成的字节码文件 目录 测试匿名内部类的实现 小结 测试lambda表达式 小结 测试方法引用 小结 三种实现方式的总结 对于lambda表达式,为什么java8要这样做? 理论 ...
- Java8系列 (一) Lambda表达式
函数式编程 在介绍Lambda表达式之前, 首先需要引入另一个概念, 函数式编程. 函数式编程是一种编程范式, 也就是如何编写程序的方法论.它的核心思想是将运算过程尽量写成一系列嵌套的函数调用,关注的 ...
- Java Lambda表达式初探
Java Lambda表达式初探 前言 本文受启发于Trisha Gee在JavaOne 2016的主题演讲Refactoring to Java 8. Java 8已经发行两年多,但很多人仍然在使用 ...
- Java8初体验(一)lambda表达式语法
感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com 本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人也是刚刚开始学习Java8,所以文中肯定有错误和理解 ...
随机推荐
- Jetson TX2 不同的工作模式
Jetson TX2 有五种工作模式,下面介绍这几种工作模式下电压.频率以及如何启动. 原理图 几种不同的工作模式 mode mode name Denver Frequency ARM Freque ...
- axios设置请求头内容
axios设置请求头中的Authorization 和 cookie 信息: GET请求 axios.get(urlString, { headers: { 'Authorization': 'Bea ...
- Linux上面mount 域控的目录 超时 然后提示 error的解决办法
mount error(112): Host is down 故障解决 https://blog.csdn.net/lepton126/article/details/89447713 之前查到过 这 ...
- tomcat单机多应用部署配合Nginx负载均衡
一.Windows 配置tomcat . 安装两个tomcat服务器以上 . 配置环境变量 CATALINA_BASE:D:\servers\Tomcat8 CATALINA_HOME:D:\serv ...
- (三)IDEA创建Spring项目
新建项目的时候,选择Spring : 在Spring的下面,有许多选项,根据自己需求选择,我是初学,就一个都没有勾选: 选择 Web Application 选项 默认是下载Spring的jar包:如 ...
- 剑指offer17:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
1 题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 2 思路和方法 (1)先在A中找和B的根节点相同的结点 (2)找到之后遍历对应位置的其他结点, ...
- 【bitset】Kth Minimum Clique
#include<bits/stdc++.h> #define B bitset<105> using namespace std; typedef long long ll ...
- ReLU、LReLU、PReLU、CReLU、ELU、SELU
ReLU.LReLU.PReLU.CReLU.ELU.SELU 2018年01月22日 22:25:34 luxiaohai的学习专栏 阅读数 28218更多 分类专栏: 深度学习 版权声明:本文 ...
- 数据库优化方案之SQL脚本优化
随着数据库数据越来越大,数据单表存在的数据量也就随之上去了,那么怎么样让我们的脚本查询数据更快呢? 在这个地方我们主要提到两个数据库类型: 1.MSSQL(该数据库我们通过执行计划来查看数据库性能在哪 ...
- ggpubr进行“paper”组图合并,也许比PS,AI更简单
本文转载自微信公众号 “生信补给站”,https://mp.weixin.qq.com/s/41iKTulTwGcY-dHtqqSnLA 多个图形进行组图展示,可以既展示一个“事情”的多个角度,也可以 ...