一、引言java8最大的特性就是引入Lambda表达式,即函数式编程,可以将行为进行传递。总结就是:使用不可变值与函数,函数对不可变值进行处理,映射成另一个值。

二、java重要的函数式接口

1、什么是函数式接口函数接口是只有一个抽象方法的接口,用作 Lambda 表达式的类型。使用@FunctionalInterface注解修饰的类,编译器会检测该类是否只有一个抽象方法或接口,否则,会报错。可以有多个默认方法,静态方法。

1.1 java8自带的常用函数式接口。public class Test {

public static void main(String[] args) {

Predicate predicate = x -> x > 185;

Student student = new Student("9龙", 23, 175);

System.out.println(

"9龙的身高高于185吗?:" + predicate.test(student.getStature()));

Consumer consumer = System.out::println;

consumer.accept("命运由我不由天");

Function function = Student::getName;

String name = function.apply(student);

System.out.println(name);

Supplier supplier =

() -> Integer.valueOf(BigDecimal.TEN.toString());

System.out.println(supplier.get());

UnaryOperator unaryOperator = uglily -> !uglily;

Boolean apply2 = unaryOperator.apply(true);

System.out.println(apply2);

BinaryOperator operator = (x, y) -> x * y;

Integer integer = operator.apply(2, 3);

System.out.println(integer);

test(() -> "我是一个演示的函数式接口");

}

/**

* 演示自定义函数式接口使用

*

* @param worker

*/

public static void test(Worker worker) {

String work = worker.work();

System.out.println(work);

}

public interface Worker {

String work();

}

}

//9龙的身高高于185吗?:false

//命运由我不由天

//9龙

//10

//false

//6

//我是一个演示的函数式接口以上演示了lambda接口的使用及自定义一个函数式接口并使用。下面,我们看看java8将函数式接口封装到流中如何高效的帮助我们处理集合。

注意:Student::getName例子中这种编写lambda表达式的方式称为方法引用。格式为ClassNmae::methodName。是不是很神奇,java8就是这么迷人。示例:本篇所有示例都基于以下三个类。OutstandingClass:班级;Student:学生;SpecialityEnum:特长。

1.2 惰性求值与及早求值惰性求值:只描述Stream,操作的结果也是Stream,这样的操作称为惰性求值。惰性求值可以像建造者模式一样链式使用,最后再使用及早求值得到最终结果。及早求值:得到最终的结果而不是Stream,这样的操作称为及早求值。

2、常用的流

2.1 collect(Collectors.toList())将流转换为list。还有toSet(),toMap()等。及早求值。public class TestCase {

public static void main(String[] args){

List studentList = Stream.of(new Student("路飞", 22, 175),

new Student("红发", 40, 180),

new Student("白胡子", 50, 185)).collect(Collectors.toList());

System.out.println(studentList);

}

}

//输出结果

//[Student{name='路飞', age=22, stature=175, specialities=null},

//Student{name='红发', age=40, stature=180, specialities=null},

//Student{name='白胡子', age=50, stature=185, specialities=null}]

2.2 filter顾名思义,起过滤筛选的作用。内部就是Predicate接口。惰性求值。

比如我们筛选出出身高小于180的同学。public class TestCase {

public static void main(String[] args){

List students = new ArrayList<>(3);

students.add(new Student("路飞", 22, 175));

students.add(new Student("红发", 40, 180));

students.add(new Student("白胡子", 50, 185));

List list = students.stream()

.filter(stu -> stu.getStature()

.collect(Collectors.toList());

System.out.println(list);

}

}

//输出结果

//[Student{name='路飞', age=22, stature=175, specialities=null}]

2.3 map转换功能,内部就是Function接口。惰性求值

public class TestCase {

public static void main(String[] args){

List students = new ArrayList<>(3);

students.add(new Student("路飞", 22, 175));

students.add(new Student("红发", 40, 180));

students.add(new Student("白胡子", 50, 185));

List names = students.stream().map(student -> student.getName())

.collect(Collectors.toList());

System.out.println(names);

}

}

//输出结果

//[路飞, 红发, 白胡子]例子中将student对象转换为String对象,获取student的名字。

2.4 flatMap将多个Stream合并为一个Stream。惰性求值

public class TestCase {

public static void main(String[] args){

List students = new ArrayList<>(3);

students.add(new Student("路飞", 22, 175));

students.add(new Student("红发", 40, 180));

students.add(new Student("白胡子", 50, 185));

List studentList = Stream.of(students,

asList(new Student("艾斯", 25, 183),

new Student("雷利", 48, 176)))

.flatMap(students1 -> students1.stream()).collect(Collectors.toList());

System.out.println(studentList);

}

}

//输出结果

//[Student{name='路飞', age=22, stature=175, specialities=null},

//Student{name='红发', age=40, stature=180, specialities=null},

//Student{name='白胡子', age=50, stature=185, specialities=null},

//Student{name='艾斯', age=25, stature=183, specialities=null},

//Student{name='雷利', age=48, stature=176, specialities=null}]调用Stream.of的静态方法将两个list转换为Stream,再通过flatMap将两个流合并为一个。

2.5 max和min我们经常会在集合中求最大或最小值,使用流就很方便。及早求值。public class TestCase {

public static void main(String[] args){

List students = new ArrayList<>(3);

students.add(new Student("路飞", 22, 175));

students.add(new Student("红发", 40, 180));

students.add(new Student("白胡子", 50, 185));

Optional max = students.stream()

.max(Comparator.comparing(stu -> stu.getAge()));

Optional min = students.stream()

.min(Comparator.comparing(stu -> stu.getAge()));

//判断是否有值

if (max.isPresent()) {

System.out.println(max.get());

}

if (min.isPresent()) {

System.out.println(min.get());

}

}

}

//输出结果

//Student{name='白胡子', age=50, stature=185, specialities=null}

//Student{name='路飞', age=22, stature=175, specialities=null}max、min接收一个Comparator(例子中使用java8自带的静态函数,只需要传进需要比较值即可。)并且返回一个Optional对象,该对象是java8新增的类,专门为了防止null引发的空指针异常。

可以使用max.isPresent()判断是否有值;可以使用max.orElse(new Student()),当值为null时就使用给定值;也可以使用max.orElseGet(() -> new Student());这需要传入一个Supplier的lambda表达式。

2.6 count统计功能,一般都是结合filter使用,因为先筛选出我们需要的再统计即可。及早求值public class TestCase {

public static void main(String[] args){

List students = new ArrayList<>(3);

students.add(new Student("路飞", 22, 175));

students.add(new Student("红发", 40, 180));

students.add(new Student("白胡子", 50, 185));

long count = students.stream().filter(s1 -> s1.getAge()

System.out.println("年龄小于45岁的人数是:" + count);

}

}

//输出结果

//年龄小于45岁的人数是:2

2.7 reducereduce 操作可以实现从一组值中生成一个值。在上述例子中用到的 count 、 min 和 max 方法,因为常用而被纳入标准库中。事实上,这些方法都是 reduce 操作。及早求值。

public class TestCase {

public static void main(String[] args){

Integer reduce = Stream.of(1, 2, 3, 4).reduce(0, (acc, x) -> acc+ x);

System.out.println(reduce);

}

}

//输出结果

//10我们看得reduce接收了一个初始值为0的累加器,依次取出值与累加器相加,最后累加器的值就是最终的结果。

三、高级集合类及收集器

3.1 转换成值收集器,一种通用的、从流生成复杂值的结构。只要将它传给 collect 方法,所有的流就都可以使用它了。标准类库已经提供了一些有用的收集器,以下示例代码中的收集器都是从 java.util.stream.Collectors 类中静态导入的。public class CollectorsTest {

public static void main(String[] args){

List students1 = new ArrayList<>(3);

students1.add(new Student("路飞", 23, 175));

students1.add(new Student("红发", 40, 180));

students1.add(new Student("白胡子", 50, 185));

OutstandingClass ostClass1 = new OutstandingClass("一班", students1);

//复制students1,并移除一个学生

List students2 = new ArrayList<>(students1);

students2.remove(1);

OutstandingClass ostClass2 = new OutstandingClass("二班", students2);

//将ostClass1、ostClass2转换为Stream

Stream classStream = Stream.of(ostClass1, ostClass2);

OutstandingClass outstandingClass = biggestGroup(classStream);

System.out.println("人数最多的班级是:" + outstandingClass.getName());

System.out.println("一班平均年龄是:" + averageNumberOfStudent(students1));

}

/**

* 获取人数最多的班级

*/

private static OutstandingClass biggestGroup(Stream outstandingClasses){

return outstandingClasses.collect(

maxBy(comparing(ostClass -> ostClass.getStudents().size())))

.orElseGet(OutstandingClass::new);

}

/**

* 计算平均年龄

*/

private static double averageNumberOfStudent(List students){

return students.stream().collect(averagingInt(Student::getAge));

}

}

//输出结果

//人数最多的班级是:一班

//一班平均年龄是:37.666666666666664maxBy或者minBy就是求最大值与最小值。

3.2 转换成块常用的流操作是将其分解成两个集合,Collectors.partitioningBy帮我们实现了,接收一个Predicate函数式接口。

将示例学生分为会唱歌与不会唱歌的两个集合。public class PartitioningByTest {

public static void main(String[] args){

//省略List students的初始化

Map> listMap = students.stream().collect(

Collectors.partitioningBy(student -> student.getSpecialities().

contains(SpecialityEnum.SING)));

}

}

3.3 数据分组数据分组是一种更自然的分割数据操作,与将数据分成 ture 和 false 两部分不同,可以使用任意值对数据分组。Collectors.groupingBy接收一个Function做转换。

如图,我们使用groupingBy将根据进行分组为圆形一组,三角形一组,正方形一组。例子:根据学生第一个特长进行分组public class GroupingByTest {

public static void main(String[] args){

//省略List students的初始化

Map> listMap =

students.stream().collect(

Collectors.groupingBy(student -> student.getSpecialities().get(0)));

}

}Collectors.groupingBy与SQL 中的 group by 操作是一样的。

3.4 字符串拼接如果将所有学生的名字拼接起来,怎么做呢?通常只能创建一个StringBuilder,循环拼接。使用Stream,使用Collectors.joining()简单容易。public class JoiningTest {

public static void main(String[] args){

List students = new ArrayList<>(3);

students.add(new Student("路飞", 22, 175));

students.add(new Student("红发", 40, 180));

students.add(new Student("白胡子", 50, 185));

String names = students.stream()

.map(Student::getName).collect(Collectors.joining(",","[","]"));

System.out.println(names);

}

}

//输出结果

//[路飞,红发,白胡子]joining接收三个参数,第一个是分界符,第二个是前缀符,第三个是结束符。也可以不传入参数Collectors.joining(),这样就是直接拼接。

四、总结本篇主要从实际使用讲述了常用的方法及流,使用java8可以很清晰表达你要做什么,代码也很简洁。本篇例子主要是为了讲解较为简单,大家可以去使用java8重构自己现有的代码,自行领会lambda的奥妙。本文说的Stream要组合使用才会发挥更大的功能,链式调用很迷人,根据自己的业务去做吧。来源 | https://urlify.cn/Jniiiu

java中max函数blog_感受 lambda 之美!相关推荐

  1. python中max函数用法_Python中max函数用法实例分析

    Python中max函数用法实例分析 更新时间:2015年07月17日 15:45:09 作者:优雅先生 这篇文章主要介绍了Python中max函数用法,实例分析了Python中max函数的功能与使用 ...

  2. java 柯里化_函数式编程(Java描述)——Java中的函数及其柯里化

    本文继续上一篇的内容 在Java中,函数可以表现为一个普通的方法.一个lambda表达式,又或者方法引用,甚至是匿名类.本文不会介绍匿名类这种形式. 方法 Java中的方法,Java使用方法这一概念来 ...

  3. python中max函数的用法解析

    python中 max函数可以输入一个参数,也可以输入两个参数.如果是一个参数,这个参数必须是可迭代的,max会for i in - 遍历一遍这个迭代器函数会返回其最大值,也可以给出key参数,这样函 ...

  4. Java中Math函数的使用

    Java中Math函数的使用 说到Java中的Math函数,大家肯定不陌生,但是在真正使用的时候却犯了难,那么多方法,我们到底需要使用哪个呢? 为此,我特地研究了一些Math常用函数的使用,以方便大家 ...

  5. Java中Math函数详解

    Java中Math函数的使用 算术计算 Math.sqrt() :计算平方根 Math.cbrt() : 计算立方根 Math.pow(a, b) : 计算a的b次方 Math.max( , ) : ...

  6. matlab 中max函数用法

    Matlab中max函数在矩阵中求函数大小的实例如下: (1)C = max(A) 返回一个数组各不同维中的最大元素. 如果A是一个向量,max(A)返回A中的最大元素. 如果A是一个矩阵,max(A ...

  7. Java中的函数传递

    转载自  Java中的函数传递 在C和C++中,函数的传递可以通过函数指针来实现.在C#中,函数传递可以通过委托.Action.Func来实现.Java中没有函数指针.没有委托,那函数要如何传递呢? ...

  8. Java中split函数的用法及使用示例

    Java中split函数的用法及使用示例 2010-05-04 10:21 日志原文:http://lhgc.blog.sohu.com/80444801.html java.lang.string. ...

  9. Matlab中max函数用法

    Matlab中max函数在矩阵中求大小: (1) C = max(A) 返回一个数组各不同维度中的最大元素. 如果A是一个向量,max(A)返回A中的最大元素. 如果A是一个矩阵,max(A)将A的每 ...

最新文章

  1. JavaScript 日期联动选择器
  2. 6.编译器拓展SEH
  3. boost::hana::detail::has_duplicates用法的测试程序
  4. OpenCV相交凸intersectConvex的实例(附完整代码)
  5. 低代码开发平台_低代码开发平台系列:6、低代码是编程技术发展大势所趋
  6. jni jvm 内存泄漏_解析Java的JNI编程中的对象引用与内存泄漏问题
  7. 重磅!GitHub发布年度机器学习榜:TensorFlow最火,PyTorch消失!
  8. PTA17、求指定层的元素个数 (10 分)
  9. MATLAB保存数据为dat格式,[转载] Matlab中的数据以.txt或.dat格式保存
  10. 2.设计模式-桥接模式
  11. python开发Day10(多进程多线程补充)
  12. [存档]使用CxServer的7个战略原因
  13. WPF实现DoEvents
  14. 4G和4G LTE之间的区别是什么?
  15. MongoDB——基础篇(文档操作)
  16. 笔记本win10更新无线服务器,win10笔记本无线驱动升级安装图文详解
  17. 大一新生先学C语言编程还是先学C语言的数据结构和算法?
  18. Open Explorer Plugin for Eclipse (eclipse 插件 在ecli
  19. Android UI换皮肤或 白天黑夜模式
  20. 最新最简便解决 teamviewre检测为商业用途 的方法

热门文章

  1. Blockathon记录——by 参赛者 张翔
  2. VisualStudio移动开发(C#、VB.NET)Smobiler开发平台——BarcodeView控件的使用方式,.Net移动开发...
  3. mysql 最基础的日常操作
  4. ES6学习笔记二 新的声明方式和变量的解构赋值!
  5. 局域网内两台9303 的管理vlan mac地址冲突解决方法
  6. 细数人们对安卓的误解
  7. 删除和创建用户的脚本
  8. RSA不对称加密,公钥加密私钥解密,私钥加密公钥解密
  9. [Ruby on Rails系列]3、初试Rails:使用Rails开发第一个Web程序
  10. windows多线程--原子操作