Java8于2014年3月份发布,其主要更新的特性有:函数式接口、Lambda 表达式、集合的流式操作、注解的更新、安全性的增强、IO\NIO 的改进、完善的全球化功能等,本文将介绍Lambda表达式与集合流试操作。

函数式接口

Java8引入的一个重要的思想就是函数式编程。 提到函数式,必须提到函数式接口。在Java8中对函数式接口的注解是@FunctionalInterface,任何一个只有一个抽象方法的接口都默认为是函数式接口,@FunctionalInterface注解是非必须的。如果在一个接口上加上该注解,那么这个接口就只能有一个抽象方法。如下

@FunctionalInterface

public interface TestInterface { void test(); }

也可以省略注解

public interface TestInterface { void test(); }

几种常见的函数式接口比如说Function 支持传入一个参数T并且返回R;

Predicate 传入一个参数T返回一个boolean类型等等。

接口

参数

返回类型

Function

T

R

Predicate

T

boolean

Supplier

None

T

UnaryOperator

T

T

Consumer

T

void

BinaryOperator

(T, T)

T

Lambda

我们可以用Lambda表达式来实例化函数式接口,避免了内部类冗余的代码。

Lambda表达式的组成

Lambda表达式有多种形式,总结来说不外乎三部分组成:第一部分为一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数,参数中可以指定类型,也可以省略类型(如果是单个参数的情况下括号可以省略,无参或者多个参数则不能省略括号);第二部分为一个箭头符号:-> 是lambda的运算符;第三部分为方法体,可以是表达式和代码块。如下

TestInterface t = () -> System.out.println("lambda");

如果有入参,第三部分是代码块,而且实现的接口有返回值的时候需要加上{}且要把结果return

public interface LongToInt { int toInt(Long i); }

LongToInt lti = i -> {

if(i != null){

return i.intValue();

} else return 0;

};

在Java8以前要想实例化接口使用匿名内部类来处理,代码显得啰嗦而不易读

new TestInterface(){

public void test() {

System.out.println("lambda");

}

}.test();

使用lambda表达式后就可以简化成一行代码

((TestInterface)() -> System.out.println("lambda")).test();

Lamdba中的方法引用

如果方法体只是简单的函数引用则可以直接使用 :: 引用,更大程度上简化我们的代码。Java8中的 :: 符号表示:符号左边的对象(List res),调用符号右边的方法(add()),参数即为lamdba表达式的参数(Integer)。

List res = Lists.newArrayList();

ints.forEach(res :: add);

Stream

java8中引用stream可以对集合进行过滤、排序、映射等操作。

生成Stream

Java8的stream分为两种,即并行和串行。可以通过Collection.parallelStream()生成一个并行流,可以通过Collection.stream()生成一个串行流(默认的stream开启的是串行流)。Stream通过StreamSupport.stream(Spliterator spliterator, boolean parallel)方法中的parallel来判断是否生成并行流。

default Stream stream() {return StreamSupport.stream(spliterator(), false);}

default Stream parallelStream() {return StreamSupport.stream(spliterator(), true);}

我们还可以将生成的stream通过stream.parallel()或stream.sequential()转换成并行或者串行。

通过方法名我们不难理解,串行流在一个线程依次执行,而并行流则是在多个线程同时执行。并行流的执行效率远远大于串行流。

Stream应用

一般在Java中使用stream有三步:第一步生成stream;第二步对stream进行转换;第三步聚合操作得到想要的结果。

Stream的中间转换操作

distinct: 对stream中的元素进行去重操作。

filter: 对stream中包含的元素使用给定的过滤函数进行过滤操作,而filter方法传的参数就是Predicate实例化,即可以. 使用上面提到的lambda表达式(新的stream中只包含Predicate中判定为true的元素)。

map: 对stream中包含的元素使用给定的转换函数进行转换操作.这个方法有三个引申方法,分别是:mapToInt,mapToLong和mapToDouble,在map中执行转换函数,再转换新的的stream元素为Integer, Long, Double类型。转换函数类型为Function,用lambda表达式比较方便。

flatMap:会把要求Function的返回值是stream即在map里面用stream的子元素再生成一个stream,把所有的子元素生成的stream压缩成一个stream。

boxed: 将LongStream、IntStream、DoubleStream转换成对应类型的Stream。

limit: 对一个stream进行截断操作,获取其前n个元素,如果原stream中包含的元素个数小于n,那就获取其所有的元素;

skip: 返回一个丢弃原stream的前n个元素后剩下元素组成的新stream,如果原stream中包含的元素个数小于n,那么返回空stream;

Stream的聚合操作

collect: 将stream元素收集起来,可以通过Collectors.toList()实现将stream转换为List的操作。

count: 得到stream的元素个数。

findFirst: 得到第一个元素。

max: 需要自定义一个Comparator来比较元素的大小,返回最大值。

min: 需要自定义一个Comparator来比较元素的大小,返回最小值。

allMatch: 判断元素是否全部符合Predicate标准。

anyMatch: 判断元素是否有一个或者多个符合Predicate标准。

noneMatch: 判断元素是否都不符合Predicate标准。

List strList = Lists.newArrayList("11 ", "213 ", " 11", "23", "145", "15 ", "2 ", " 3", "");

List ints = Lists.partition(strList, 3).stream().flatMapToInt(strs -> strs.stream().filter(str -> str != null && !Objects.equals(str, "")).mapToInt(str -> Integer.valueOf(str.trim()))).distinct().limit(5).skip(3).boxed().collect(Collectors.toList());

上面的例子是把一个List,先通过Guava Lists将该list按每组3个拆分生成List>再转换为Stream>,再flatMapToInt,在map里面再将list转换为Stream,过滤掉空字符串和null,再mapToInt去重,取前5个,再丢弃前三个元素,再转换成一个List。

注:所有的聚合操作、foreach操作都会把stream关闭,如果一个stream被关闭后,不能再次对stream进行任何操作。

Java中lambda表达式去重_JAVA8中Lambda和Stream相关推荐

  1. 【Java】使用lambda表达式获取list中所有对象的某个属性以及获取特定属性的某一个对象

    使用lambda表达式获取list中所有对象的某个属性以及获取特定属性的某一个对象 获取List中所有对象的某个属性 获取List中某个特定属性的对象 获取List中所有对象的某个属性 案例如下:获取 ...

  2. python使用函数的优点-Lambda表达式在Python中的优点和缺点

    学过python的人,相信都接触过Lambda表达式.本文就来谈谈Lambda表达式在Python中的优点和缺点.一方面,Lambda函数的减少了代码的行数,方便又简洁.另一方面,Lambda表达式有 ...

  3. 通过lambda表达式根据对象中的时间排序

    通过lambda表达式根据对象中的时间排序 话不多说,直接上代码!! //根据发送时间排序,时间按升序排序(时间小的排前面) List<ChatRecord> newCrList = cr ...

  4. [C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别(日文翻译)...

    Lambda表达式与匿名方法的区别 那么,为什么Lambda表达式比匿名方法写起来要短呢?这种像变戏法一样的手法真的能用吗?有没有重要信息遗漏掉呢?为了回答这些问题,就让我们把匿名方法和Lambda表 ...

  5. php有lambda表达式吗,Python中lambda表达式的简单介绍(附示例)

    本篇文章给大家带来的内容是关于Python中lambda表达式的简单介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 一:匿名函数的定义 lambda parameter ...

  6. java lambda表达式_高性能的 Lambda 表达式,简洁优雅图文并茂

    来源:知乎 Mingqi 链接:https://www.zhihu.com/question/20125256/answer/324121308 有网友问,Lambda 表达式有何用处?如何使用?在P ...

  7. java8 list 去重_Java8中的Stream,一行代码,让集合操作飞起来

    简介 java8也出来好久了,接口默认方法,lambda表达式,函数式接口,Date API等特性还是有必要去了解一下.比如在项目中经常用到集合,遍历集合可以试下lambda表达式,经常还要对集合进行 ...

  8. java8 lamda表达式相等_java8之lambda表达式(lambda表达式语法)

    到目前为止,在Java中向其他代码传递一段代码并不是很容易.你不可能将代码块到处传递.由于java是一个面向对象的语言,因此你不得不构建一个属于某个类的对象,由它的某个方法来包含所需的代码. lamb ...

  9. java lambda表达式条件_Java 8 Lambda表达式一看就会

    匿名内部类的一个问题是:当一个匿名内部类的实现非常简单,比如说接口只有一个抽象函数,那么匿名内部类的语法有点笨拙且不清晰.我们经常会有传递一个函数作为参数给另一个函数的实际需求,比如当点击一个按钮时, ...

最新文章

  1. 双一流高校出新规:研究生未经导师同意发论文,不得用于毕业、评奖!
  2. l bfgs算法java代码_优化算法——拟牛顿法之L-BFGS算法
  3. oracle sql 调用自定义函数_PSCAD入门教程(第7节):怎样调用fortran编写的自定义函数?(附模型)...
  4. python如何初始化一个二维数组_使用Python实现一个简单的商品期货布林指标突破策略...
  5. Nacos(十一)之NacosSync 介绍
  6. Linux命令-自动挂载文件/etc/fstab功能详解
  7. c++椭圆最小二乘法原理_c++ 椭圆拟合之最小二乘法(图像处理)
  8. 双11 iPhone再降价:24期免息 四舍五入等于不要钱!
  9. hiho #1014 : Trie树(模板)
  10. Python3网络爬虫快速入门实战解析——对大佬部分代码失效的修改
  11. 书籍推荐——按角色划分
  12. 【python】Tkinter可视化窗口(一)
  13. pam_limits(sshd:session): unknown limit item 'noproc'
  14. python修改html,Python爬虫精简步骤 HTML基础
  15. 如何向github上传代码
  16. php用redis实现队列,PHP使用Redis实现队列
  17. 根据银行卡号查询银行卡名称
  18. 第9天Sqltie数据库
  19. 跟我学在高德地图——标注我的位置
  20. (转载)Android 让WebView完美支持https双向认证(SSL)

热门文章

  1. Directx11教程(18) D3D11管线(7)
  2. 深入理解 C# 协变和逆变
  3. 2013年1月18日调试触发器“表发生了变化,触发器或函数不能读它”的出现原因,以及解决方案...
  4. ORACLE 调试输出,字符串执行函数
  5. 使用Gridview绑定数据库中的图片
  6. python与java、php、go的优势对比
  7. MySQL导出数据遇到secure-file-priv问题的解决方法
  8. centos7下配置golang1.7.1环境(自己做测试了)
  9. Elasticsearch和MongoDB对比
  10. JS的ES6模板字符串(拼接、变量、循环、函数)