github源码

大前提:jdk8  允许lambda表达式  最好在maven中加入

<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

只总结真香案例!!!

案例一:

从"1" "2" "bilibili" "of" "codesheep" "5" "codesheep" "5" "at" "BILIBILI" "codesheep" "23" "CHEERS" "6"中
找出所有 长度>=5的字符串,并且忽略大小写、去除重复字符串,然后按字母排序,最后用“ * ”连接成一个字符串输出
List<String> list = new ArrayList<>();
list.add("1");
···
list,add("6");
String str = list.stream()//list转为stream流
.filter(i -> !isNum(i))//过滤出不是数字的 也就是 得到字符 isNum是自己封装的方法
.filter(i -> i.length()>5)//过滤出长度大于5的
.map(i -> i.toLowerCase())//转为小写
.distinct()//去重
.sorted(Comparator.naturalOrder())//字符串排序
.collect(Collectors.joining("*"));//字符串连接
System.out.println(str);

案例二:

public class Lambda2 {
public static void main(String[] args) {
/**
* 函数接口:Predict
* 抽象方法:test(T t)
* 参数:T
* 返回值类型:Boolean
* 功能:判断真假
* 示例:判断学生身高
* 结果:韩非的身高高于185吗?: false
*/
Predicate<Integer> predicate = x -> x > 185;
Student student = new Student("韩非", 23, 175);
System.out.println("韩非的身高高于185吗?: " + predicate.test(student.getLength())); /**
* 函数接口:Consumer
* 抽象方法:accept(T t)
* 参数:T
* 返回值类型:void
* 功能:消费消息
* 示例:输出值
* 结果:列东方位 青龙
*/
Consumer<String> consumer = System.out::println;
consumer.accept("列东方位 青龙"); /**
* 函数接口:Function
* 抽象方法:R apply(T t)
* 参数:T
* 返回值类型:R
* 功能:将T映射为R(转换功能)
* 示例:输出student名字
* 结果:韩非
*
* 备注:Student::getName这种lambda表达式写法被称为 方法引用 格式为 ClassName::MethodName
*/
Function<Student, String> function = Student::getName;
String name = function.apply(student);
System.out.println(name); /**
* 函数接口:Supplier
* 抽象方法:T get()
* 参数:void
* 返回值类型:T
* 功能:生产消息
* 示例:工厂方法
* 结果:10
*/
Supplier<Integer> supplier = () -> Integer.valueOf(BigDecimal.TEN.toString());
System.out.println(supplier.get()); /**
* 函数接口:UnaryOperator
* 抽象方法:T apply(T t)
* 参数:T
* 返回值类型:T
* 功能:一元操作
* 示例:逻辑非(!)
* 结果:false
*/
UnaryOperator<Boolean> unaryOperator = uglily -> !uglily;
Boolean apply2 = unaryOperator.apply(true);
System.out.println(apply2);
//使用BinaryOperator函数式接口 抽象方法T apply(T t, U u) 功能:二元操作 参数T,U 返回值类型T 求两个数乘积 /**
* 函数接口:BinaryOperator
* 抽象方法:T apply(T t, U u)
* 参数:T,U
* 返回值类型:T
* 功能:二元操作
* 示例:求两个数乘积
* 结果: 6
*/
BinaryOperator<Integer> 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();
}
}

案例三:

/**
* 惰性求值:只描述Stream,操作的结果也是Stream,这样的操作称为惰性求值。惰性求值可以像建造者模式一样链式使用,最后再使用及早求值得到最终结果。
* 及早求值:得到最终的结果而不是Stream,这样的操作称为及早求值。
*
* 常用的流:collect(Collectors.toList())
* 功能:将流转为list
* 结果:[Student(name=路飞, age=22, length=175, specialisies=null), Student(name=红发, age=40, length=180, specialisies=null)]
*/
List<Student> studentList = Stream.of(
new Student("路飞", 22, 175),
new Student("红发", 40, 180)
).collect(Collectors.toList());
System.out.println(studentList);

案例四:

/**
* 常用的流:filter
* 功能:顾名思义,起过滤筛选的作用。内部就是Predicate接口。惰性求值。
* 示例:筛选出身高小于180的同学
* 结果:[Student(name=路飞, age=22, length=175, specialisies=null)]
*/
List<Student> students = new ArrayList<>(3);
students.add(new Student("路飞", 22, 175));
students.add(new Student("红发", 40, 180));
students.add(new Student("白胡子", 50, 185));
List<Student> list = students.stream()
.filter(stu -> stu.getLength() < 180)
.collect(Collectors.toList());
System.out.println(list);

案例五:

/**
* 常用的流:map
* 功能:转换功能,内部就是Function接口。惰性求值
* 示例:获取所有同学的名字
* 结果:[路飞, 红发, 白胡子]
*/
List<Student> students = new ArrayList<>(3);
students.add(new Student("路飞", 22, 175));
students.add(new Student("红发", 40, 180));
students.add(new Student("白胡子", 50, 185));
List<String> names = students.stream().map(student -> student.getName())
.collect(Collectors.toList());
System.out.println(names);

案例六:

/**
* 常用的流:flatMap
* 功能:将多个Stream合并为一个Stream。惰性求值
* 示例:调用Stream.of的静态方法将两个list转换为Stream,再通过flatMap将两个流合并为一个
* 结果:[
* Student(name=路飞, age=22, length=175, specialisies=null),
* Student(name=红发, age=40, length=180, specialisies=null),
* Student(name=白胡子, age=50, length=185, specialisies=null),
* Student(name=艾斯, age=25, length=183, specialisies=null),
* Student(name=雷利, age=48, length=176, specialisies=null)
* ]
*/
List<Student> students = new ArrayList<>(3);
students.add(new Student("路飞", 22, 175));
students.add(new Student("红发", 40, 180));
students.add(new Student("白胡子", 50, 185));
List<Student> studentList = Stream.of(students,
Arrays.asList(new Student("艾斯", 25, 183),
new Student("雷利", 48, 176)))
.flatMap(students1 -> students1.stream()).collect(Collectors.toList());
System.out.println(studentList);

案例七:

/**
* 常用的流:max min
* 功能:我们经常会在集合中求最大或最小值,使用流就很方便。及早求值。
* 示例:得到年龄最大和最小的同学
* 结果:Student(name=白胡子, age=50, length=185, specialisies=null)
* Student(name=路飞, age=22, length=175, specialisies=null)
*
* 补充:max、min接收一个Comparator(例子中使用java8自带的静态函数,只需要传进需要比较值即可。)
* 并且返回一个Optional对象,该对象是java8新增的类,专门为了防止null引发的空指针异常。可以使用max.isPresent()判断是否有值;
* 可以使用max.orElse(new Student()),当值为null时就使用给定值;也可以使用max.orElseGet(() -> new Student());
* 这需要传入一个Supplier的lambda表达式。
*/
List<Student> students = new ArrayList<>(3);
students.add(new Student("路飞", 22, 175));
students.add(new Student("红发", 40, 180));
students.add(new Student("白胡子", 50, 185));
Optional<Student> max = students.stream()
.max(Comparator.comparing(stu -> stu.getAge()));
Optional<Student> 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());
}

案例八:

/**
* 常用的流:count
* 功能:统计功能,一般都是结合filter使用,因为先筛选出我们需要的再统计即可。及早求值
* 示例:统计年龄小于45的人数
* 结果:年龄小于45岁的人数是:2
*/
public static void main(String[] args) {
List<Student> 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() < 45).count();
System.out.println("年龄小于45岁的人数是:" + count);
}

案例九:

/**
* 常用的流:reduce
* 功能:reduce 操作可以实现从一组值中生成一个值。前面案例用到的 count 、 min 和 max 方法,因为常用而被纳入标准库中。事实上,这些方法都是 reduce 操作。及早求值。
* 示例:reduce接收了一个初始值为0的累加器,依次取出值与累加器相加,最后累加器的值就是最终的结果
* 结果:10
*/
public static void main(String[] args) {
Integer reduce = Stream.of(1, 2, 3, 4).reduce(0, (acc, x) -> acc+ x);
System.out.println(reduce);
}

案例十:

 /**
* 收集器,一种通用的、从流生成复杂值的结构。只要将它传给 collect 方法,所有
* 的流就都可以使用它了。标准类库已经提供了一些有用的收集器,以下示例代码中的收集器都是从 java.util.stream.Collectors 类中静态导入的。
*
*
* 结果:人数最多的班级是:一班 一班平均年龄是:37.666666666666664
*/
public static void main(String[] args) {
List<Student> 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<Student> students2 = new ArrayList<>(students1);
students2.remove(1);
OutstandingClass ostClass2 = new OutstandingClass("二班", students2);
//将ostClass1、ostClass2转换为Stream
Stream<OutstandingClass> classStream = Stream.of(ostClass1, ostClass2);
OutstandingClass outstandingClass = biggestGroup(classStream);
System.out.println("人数最多的班级是:" + outstandingClass.getName());
System.out.println("一班平均年龄是:" + averageNumberOfStudent(students1));
} /**
* 获取人数最多的班级
* 无论选择哪种返回值语句都可以
* 区别是 Optional中对null做了许多封装,可以进行空值的校验
* orElseGet方法 如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值
*/
private static OutstandingClass biggestGroup(Stream<OutstandingClass> outstandingClasses) {
// return outstandingClasses.max(Comparator.comparing(stu -> stu.getStudents().size())).get();
return Optional.of(outstandingClasses.max(Comparator.comparing(stu -> stu.getStudents().size())).get()).orElseGet(OutstandingClass:: new );
}
/**
* 计算平均年龄
*/
private static double averageNumberOfStudent(List<Student> students) {
return students.stream().collect(Collectors.averagingInt(Student::getAge));
}

案例十一:

/**
* 常用的流:Predicate
* 功能:将流分解成两个集合,接收一个Predicate函数式接口。
* 示例:按照会sing的和不会sing对学生进行分拆
* 结果:{
* false=[Student(name=红发, age=40, length=180, specialisies=swimming), Student(name=白胡子, age=50, length=185, specialisies=dance)],
* true=[Student(name=路飞, age=23, length=175, specialisies=sing)]
* }
* 和Collectors.groupingBy() 分组类似
*/
List<Student> students = new ArrayList<>(3);
Student stu1 = new Student("路飞", 23, 175);
stu1.setSpecialisies("sing");
students.add(stu1);
Student stu2 = new Student("红发", 40, 180);
stu2.setSpecialisies("swimming");
students.add(stu2);
Student stu3 = new Student("白胡子", 50, 185);
stu3.setSpecialisies("dance");
students.add(stu3);
Map<Boolean, List<Student>> listMap = students.stream().collect(
Collectors.partitioningBy(stu ->
stu.getSpecialisies().
contains(SpecialityEnum.SING.name)));
System.out.println(listMap); //使用Collectors.groupingBy()也可完成同样的功能
Map<Boolean, List<Student>> li = students.stream().collect(Collectors.groupingBy(student -> student.getSpecialisies().contains(SpecialityEnum.SING.name)));
System.out.println(li);

案例十二:

/**
* 常用的流:数据分组groupingBy 分组条件通常会被作为Map的key
* 功能:数据分组是一种更自然的分割数据操作,与将数据分成 ture 和 false 两部分不同,可以使用任意值对数据分组。Collectors.groupingBy接收一个Function做转换。
* 示例:按照会特长对学生进行分组
* 结果:{
* swimming=[Student(name=红发, age=40, length=180, specialisies=swimming)],
* sing=[Student(name=路飞, age=23, length=175, specialisies=sing)],
* dance=[Student(name=白胡子, age=50, length=185, specialisies=dance)]
* }
* 分组条件可以拼接多个 但是要和声明的类型(Map的key)一致
* 示例:声明类型是String
* 分组条件:特长***名字 stu.getSpecialisies()+"***"+stu.getName()
* 结果:{
* dance***白胡子=[Student(name=白胡子, age=50, length=185, specialisies=dance)],
* sing***路飞=[Student(name=路飞, age=23, length=175, specialisies=sing)],
* swimming***红发=[Student(name=红发, age=40, length=180, specialisies=swimming)]
* }
*/
List<Student> students = new ArrayList<>(3);
Student stu1 = new Student("路飞", 23, 175);
stu1.setSpecialisies("sing");
students.add(stu1);
Student stu2 = new Student("红发", 40, 180);
stu2.setSpecialisies("swimming");
students.add(stu2);
Student stu3 = new Student("白胡子", 50, 185);
stu3.setSpecialisies("dance");
students.add(stu3);
Map<String, List<Student>> listMap =
students.stream().collect(
Collectors.groupingBy(stu -> stu.getSpecialisies()));
System.out.println(listMap);
Map<String, List<Student>> lis =
students.stream().collect(
Collectors.groupingBy(stu -> stu.getSpecialisies()+"***"+stu.getName()));
System.out.println(lis);

案例十三:

/**
* 常用的流:拼接joining 有三个参数,第一个是分隔符,第二个是前缀符,第三个是后缀符。也可以不传入参数Collectors.joining(),这样就是直接拼接。
* 功能:类似stringbuilder这样循环append("a") append("b") append("c")拼接
* 示例:将所有学生的名字拼接起来
* 结果:[路飞,红发,白胡子]
*/
List<Student> 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);

案例十四:

/**
* 接口:Consumer 顾名思义,它是“消费者的含义”,接受参数而不返回值
* 示例:打印消息
* 结果:hello world
* hello java
* hhhhh
* hhhhh
* hhhhh
*/
Consumer c = System.out::println;
c.accept("hello world");//打印hello world
c.accept("hello java");//打印hello java
c.andThen(c).andThen(c).accept("hhhhh");//连续打印三次hhhhh 而不是hello java hello java hhhhh

案例十五:

/**
* 接口:Function 代表的含义是“函数”,其实和上面的 Consumer有点像,不过 Function既有输入,也有输出,使用更加灵活
* 示例:对一个整数先乘以 2,再计算平方值
* 结果:36 5184
* 过程:先走apply传递参数3 然后执行f1=3*2得到6 然后执行f2=6*6得到36
* 先走apply传递参数3 然后执行f1=3*2得到6 然后执行f2=6*6得到36 然后执行f1=36*2得到72 然后执行f2=72*72得到5184
* andThen的参数就是 Function类型的after 即接下里执行的函数
*/
Function<Integer,Integer> f1 = i -> i*2;
Function<Integer,Integer> f2 = i -> i*i;
Consumer c = System.out::println; c.accept(f1.andThen(f2).apply(3));
c.accept(f1.andThen(f2).andThen(f1).andThen(f2).apply(3));

案例十六:空值校验

/**
* 接口:Optional 本质是个容器,你可以将你的变量交由它进行封装,这样我们就不用显式对原变量进行 null值检测,防止出现各种空指针异常
* 示例:获取学生科目的成绩
*/
public static Integer getScore(Student stu){
return Optional.ofNullable(stu).map(Student::getSubject).map(Subject::getScore).orElse(null);
}
//常规做法 判断学生是否为空,不为空得到学科,判断学科是否为空,不为空取值 如果有很多层包着 简直是俄罗斯套娃 惨不忍睹
public static Integer getScore(Student stu){
if(stu != null){
Subject sub = stu.getSubject();
if (sub != null){
return sub.getScore();
}
}
return null;
}

lambda之美的更多相关文章

  1. 感受lambda之美,推荐收藏,需要时查阅

    一.引言二.java重要的函数式接口1.什么是函数式接口1.1 java8自带的常用函数式接口.1.2 惰性求值与及早求值2.常用的流2.1 collect(Collectors.toList())2 ...

  2. 来探讨一下最近面试问的ThreadLocal问题

    中高级阶段开发者出去面试,应该躲不开ThreadLocal相关问题,本文就常见问题做出一些解答,欢迎留言探讨. ThreadLocal为java并发提供了一个新的思路, 它用来存储Thread的局部变 ...

  3. JAVA8中Predicate,Consumer,UnaryOperator,Function接口的应用

    笔者平时时间有限,直接贴代码,关于几个接口的差别,可以查看这两篇文章 感受lambda之美,推荐收藏,需要时查阅 https://juejin.im/post/5ce66801e51d455d850d ...

  4. java代码之美(1)---Lambda

    Lambda 一.概述 1.什么是Lambda表达式 Lambda 表达式是一种匿名函数,简单地说,它是没有声明的方法,也即没有访问修饰符.返回值声明和名字. 它可以写出更简洁.更灵活的代码.作为一种 ...

  5. Delegate &&Lambda

    匿名函数及委托的使用: public delegate void NoReturnNoParaOutClass();//delegate can be defined in class or out ...

  6. Lambda in Java VS in C#

    核心+变化 “凡是钱能解决的问题,就不是大问题.有很多问题是钱无法解决的,比如生老病死,比如不再相爱.”,看过<蜗居>的朋友一眼就能认出来.虽然这部电视剧讲的是chugui,但是毫无违和感 ...

  7. 泛化之美--C++11可变模版参数的妙用

    1概述 C++11的新特性--可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意个数.任意类型的参数.相比C++98/03 ...

  8. 20155326刘美岑 2016-2017-2 《Java程序设计》第5周学习总结

    20155326刘美岑 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 使用 try.catch (1)java中所有的错误都会被打包为对象,如果愿意,可以尝 ...

  9. [转]C# 指针之美

     将C#图像库的基础部分开源了(https://github.com/xiaotie/GebImage).这个库比较简单,且离成熟还有一段距离,但它是一种新的开发模式的探索:以指针和非托管内存为主的C ...

随机推荐

  1. 主机Redis服务迁移到现有Docker Overlay环境

    记录最后一次对中型2C企业级项目的容器化改造 hello, 好久不见,之前文章记录了一个实战的2C分布式项目的改造过程,结果如下: 其中Redis并未完成容器化改造(目前是主机单点),本文记录将Red ...

  2. 区间dp 能量项链 洛谷p1063

    题目大意:如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为 (Mars单位),新产生的珠子的头标记为m,尾标记为n. 需要时,Mars人就用吸盘夹住 ...

  3. 苹果XR手机的音频体验测试总结

    苹果XR手机的音频   苹果XR算是苹果手机历史上一个里程碑的型号了,是苹果憋了两年的大招,连苹果9的称号就不要了.直接是X.说明苹果对它给予的希望很大.作为一个音频算法工程师,一直想体验一下XR的音 ...

  4. Python实用笔记 (20)面向对象编程——继承和多态

    当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类(Base class.Super class). ...

  5. vue基础入门(2.1)

    2.vue基础用法 2.1.事件处理 2.1.1.监听事件 使用v-on:事件名称 = '事件处理函数'的形式来监听事件,事件处理函数要写在methods后面的对象中 <!DOCTYPE htm ...

  6. python简易版微信或QQ轰炸

    ​ 在讲解代码之前我们先来回忆一下,平时我们发送消息时,先打开微信或QQ的界面,在信息栏中输入你要发送的内容在点击发送或通过快捷键发送.如果要发送表情时,先打开微信或QQ的界面,在点击表情包中你要发送 ...

  7. Linux傻瓜式七步完美安装Python3.7

    1 安装依赖包 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-deve ...

  8. Meta标签大全_web开发常用meta整理

    meta标签提供关于HTML文档的元数据.元数据不会显示在页面上,但是对于机器是可读的.它可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 web 服务. 必要属性 属性 值 描 ...

  9. Java基础笔记05-06-07-08

    五.今日内容介绍 1.方法基础知识 2.方法高级内容 3.方法案例 01方法的概述 * A: 为什么要有方法 * 提高代码的复用性 * B: 什么是方法 * 完成特定功能的代码块. 02方法的定义格式 ...

  10. 一、python 基础之基础语法

    一.变量命名规则 1.驼峰命名 大驼峰 MyName = 'leon' 小驼峰 myName = 'Amy' 2.下划线命名 my_name = 'jack' 建议:变量名或者文件名使用下划线命名方式 ...