lamda表达式与Stream 流操作,reduce,flatMap,groupingBy等
/**
* 符合lambda表达式的接口也叫函数式接口:
* 除了默认方法和Object类的方法外,只有一个抽象方法的接口才能符合lambda表达式的要求
* 可以使用@FunctionalInterface来校验,如果没报错就是符合要求的
*
*
*/
@FunctionalInterface
public interface Animal { default String getName(){
return "animal";
} void eat(); }
//无参有返回
public interface Person {
String getName();
}
//有参无返回
public interface Sckool { void learn(String name);
}
//有参有返回
public interface Student {
String conCat(String str,String str2);
}
package lambda; public class testLambda {
public static void main(String[] args) {
//要调用一个接口的方法,要么定义一个类来实现该接口,要么使用匿名内部类:
//下面使用匿名内部类: eat(new Animal() {
@Override
public void eat() {
System.out.println("动物吃东西");
}
});
/**
* 如果匿名内部类只有一个方法,可以使用lambda表达式替换:
* 总共分下面4种情况:
* 无参无返回格式:
* 单条语句时()->xxx ;多条语句时()->{xx;aa;}
* 无参有返回:
* 单条语句时()->xxx;多条语句时()->{xx; return aa;}
* 有参无返回:
* 单条语句单个参数时:a->xxx;多条语句单个参数时a->{xx;cc;}
* 单条语句多个参数时:(a,b)->xxx;多条语句多个参数时(a,b)->{xx;cc;}
*
* 有参有返回:
* 单条语句单个参数时:a->xxx;多条语句单个参数时a->{xx;return cc;}
* 单条语句多个参数时:(a,b)->xxx;多条语句多个参数时(a,b)->{xx; return cc;}
*/ //-------- 无参无返回格式:
//单条语句时()->xxx
eat(()-> System.out.println("aaa")); //多条语句时()->{xx;aa;}
eat(()->{
System.out.println("dd");
System.out.println("cc");
}); //---------无参数有返回格式:
// 单条语句时()->xxx;
String name=getName(()->"kk"); //多条语句时()->{xx; return aa;}
getName(()->{
System.out.println("dd");
return "cc";
}); //--------有参数无返回时 //单条语句单个参数时
learn(a-> System.out.println(a)); //多条语句单个参数时a->{xx;cc;}
learn(a->{
System.out.println("lll");
System.out.println("cc");
}); //单条语句多个参数时
// learn((a,b)-> System.out.println(a+b)); //多条语句多个参数时(a,b)->{xx;cc;}
/**
*
* learn((a,b)-> {
System.out.println("lll");
System.out.println("cc");
}); *
*/ //---------有参数有返回 //单条语句单个参数时:a->xxx;
// learn(a-> "dd"); //多条语句单个参数时a->{xx;return cc;}
/**
* learn(a->{
System.out.println("lll");
return "ss";
});
*
*
*/ //单条语句多个参数时:(a,b)->xxx
String subject=concat((a,b)->a+b); //多条语句多个参数时(a,b)->{xx; return cc;}
String subject2=concat((a,b)->{
System.out.println("ddd");
return a+b;
}); /**
*
* 我们使用lambda表达式时候,都是要实现一个方法,如果你要实现的方法刚好其他类有,那么就可以引用其他类的方法过来当做该匿名内部类的实现
* 所以方法的引用分为:
* 静态方法的引用,如System.out:println
* 非静态方法的引用:如 new Dog()::eat;
* 参数类型方法的引用,例如一个要实现的方法参数是String a,String b ,期望的结果是a+b,那么可以引用String::concat方法
*
*
*/ learn(System.out::print); //刚好learn的内部类要实现的方法跟System.out的方法长得一样,所以可以引用该方法当做自己的实现方法
eat(new testLambda()::haveMeal);//非静态方法的引用
String str=concat(String::concat);//参数
System.out.println(str); } public static void eat(Animal animal){
animal.eat();
}
public static String getName(Person person){
return person.getName();
}
public static void learn(Sckool sckool){
sckool.learn("java");
}
public static String concat(Student student){
return student.conCat("java","php");
} public void haveMeal(){
System.out.println("吃饭");
}
}
//stream 流:
package lambda; import java.math.BigDecimal; public class Cat {
private String name;
private BigDecimal price; public Cat(String name, BigDecimal price) {
this.name = name;
this.price = price;
} @Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", price=" + price +
'}';
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public BigDecimal getPrice() {
return price;
} public void setPrice(BigDecimal price) {
this.price = price;
}
}
package lambda; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream; public class testLambda {
public static void main(String[] args) {
List<Cat> list=new ArrayList<>();
list.add(new Cat("k",new BigDecimal("200")));
list.add(new Cat("g",new BigDecimal("100")));
list.add(new Cat("k",new BigDecimal("300")));
list.add(new Cat("l",new BigDecimal("400")));
list.add(new Cat("b",new BigDecimal("500")));
list.add(new Cat("b",new BigDecimal("501")));
/**
* Stream流:跟IO的流是不一样的,比较适当的比喻可以当做一个管道,数据从管道一端流经另一端,中间会经过多个操作,如过滤,排序
*
* 流程: 源 ------过滤----排序---终止-结果
*
* 所有操作分为三类
* 1.创建流
* 2.中间操作(惰性操作) : 凡是返回值类型是Stream的都是中间操作,如果只有中间操作,没有终止操作,流是不会执行的
* 3.终值操作
*
*
*
* 创建:
* Collection.stream();
* Arrays.asList("a","b").stream();
* Stream.of("a","b");
*
*/ /**
* 流的特点:
* 1.不能重复使用,每经过一个中间操作都返回新的流,之前的流就关闭了
* 2.最多只能有一个终值操作,并且终值操作都是在最后
* 3.执行顺序:
* 假如一个流经过 filter--sorted操作,顺序是一个元素先经过filter--sorted 然后下一个元素经过filter--sorted,并不是所有元素先经过filter,然后经过sorted
*
*
*/
Stream<Cat> stream = list.stream();
//过滤操作是中间操作,如果没有终值操作就不会执行
Stream<Cat> stream2 = stream.filter(a -> {
System.out.println("中间操作是惰性的,这句话不会输出");
return a.getName().equals("b");
});
//下面的操作会报错:java.lang.IllegalStateException: stream has already been operated upon or closed
//因为stream在上一步执行完filter就关闭了
/*stream.filter(a-> {
System.out.println("流不能重复使用");
return a.getName().equals("b");
}).toArray();*/ Object[] bs = stream2.filter(a -> {
System.out.println("有终值操作toArray,所以该方法会被执行");
return a.getName().equals("b");
}).toArray(); //测试流是一个一个执行元素还是全部一起执行 list.stream().filter(a->{
System.out.println("过滤操作");
return !a.getName().equals("oo");
}).forEach(a-> System.out.println("遍历操作")); //输出结果: 过滤操作 遍历操作 过滤操作 遍历操作 ..... //常用的Strem API //过滤filter:上面的例子
System.out.println(Arrays.toString(bs)); //peek 和 forEach操作,peek不是终值操作,执行后还能继续执行其他中间操作,forEach是终值操作 list.stream().peek(System.out::println); //不会打印数据,因为中间操作是懒惰的
list.stream().peek(System.out::println).toArray();
list.stream().forEach(System.out::println);//终值操作,直接会输出结果 //map 将元素按照一定规则映射成另外一个元素
List<String> nameList = list.stream().map(a -> a.getName()).collect(Collectors.toList());
System.out.println(nameList); //distinct 去重
List<String> distionctNameList = list.stream().map(a -> a.getName()).distinct().collect(Collectors.toList());
System.out.println(distionctNameList); //sorted 排序
List<Cat> sortList = list.stream().sorted((a, b) -> b.getPrice().compareTo(a.getPrice())).collect(Collectors.toList());
System.out.println(sortList);
//limit 操作
List<Cat> limitList = list.stream().limit(2).collect(Collectors.toList());
System.out.println(limitList); //mapToInt和reuduce用户sum()操作时,调用int reduce(int identity, IntBinaryOperator op);所有元素op操作后加上identity的值就得到sum()的值了 int reduce = list.stream().mapToInt(a -> a.getPrice().intValue()).reduce(0, (a, b) -> a + b); //2001
int reduce2 = list.stream().mapToInt(a -> a.getPrice().intValue()).reduce(-1, (a, b) -> a + b);//2000
int reduce3 = list.stream().mapToInt(a -> a.getPrice().intValue()).reduce(20, (a, b) -> a + b);//2021
System.out.println(reduce);
System.out.println(reduce2);
System.out.println(reduce3);
//BigDecimal payAmount = billMastList.stream().map(a -> a.getAmtBillPayment()).reduce(BigDecimal.ZERO, BigDecimal::add); 金额处理 //skip操作 跳过多少个元素,从1开始算
List<Cat> skipList = list.stream().skip(1).collect(Collectors.toList());
System.out.println(skipList);
//价格最贵的 max(Comparator<? super T> comparator)
Cat cat = list.stream().max((a, b) -> a.getPrice().compareTo(b.getPrice())).get();
System.out.println(cat); // boolean anyMatch(Predicate<? super T> predicate),判断是否有比600价格贵的
boolean b = list.stream().allMatch(a -> a.getPrice().compareTo(new BigDecimal(600)) > 0);
boolean b2 = list.stream().anyMatch(a -> a.getPrice().compareTo(new BigDecimal(500)) > 0);
System.out.println(b);
System.out.println(b2);
//findAny() 获取任意一个
Cat cat1 = list.stream().findAny().get();
System.out.println(cat1); //findFirst() 获取第一个
Cat cat2 = list.stream().findFirst().get();
System.out.println(cat2);
//flatMap:比较像降维打击,如三维空间变成二维空间,具体的意思是每个元素经过处理,生成新的流.例如这里每个cat获取它的名字组成一个新的集合
//再举个例子,订单跟商品,一个订单集合经过flatMap,获取每个订单的商品集合组成一个新的流
List<String> flatMapList = list.stream().flatMap(a -> Stream.of(a.getName())).collect(Collectors.toList());
System.out.println(flatMapList);
//list转map 第一个参数是key值,第二个参数value值,第三个参数是key重复时,value如何进行合并
Map<String, BigDecimal> map = list.stream().collect(Collectors.toMap(a -> a.getName(), a -> a.getPrice(),(c, d)->c.add(d)));
System.out.println(map);
//分组功能
List<PerSon> list=new ArrayList<>();
list.add(new PerSon("yang",12));
list.add(new PerSon("yang",20));
list.add(new PerSon("ming",12));
list.add(new PerSon("ming",362));
list.add(new PerSon("tt",12));
list.add(new PerSon("kk",12));
Map<String, List<PerSon>> collect = list.stream().collect(Collectors.groupingBy(PerSon::getName)); //会分成四组,根据名字来分组
//注意 list转map如果value值为null会报,如果key重复,不处理也会报错,处理最好如下所示
custmerNameMap = customerInfoBatchList.stream().filter(a->StringUtils.isNotBlank(a.getCustomerName())) //过滤空值
.collect(Collectors.toMap(XfaceCustomerInfoListForBatchResponseSubDTO::getCustomerId, XfaceCustomerInfoListForBatchResponseSubDTO::getCustomerName,(k1,k2)->k1)); //
(k1,k2)->k1)代表key重复时,取第一个
//总结:所有API都不用记!!要用任何一个方法,点开Stream类可以查看到,或者idea工具提示可以找到任何一个方法,每个方法的参数都是一个接口,找到该接口看看其要实现的方法,然后使用lambda表达式就可以了 } }
idea安装插件可以对stream流进行debug:
lamda表达式与Stream 流操作,reduce,flatMap,groupingBy等的更多相关文章
- java8 stream流操作的flatMap(流的扁平化)
https://mp.weixin.qq.com/s/7Fqb6tAucrl8UmyiY78AXg https://blog.csdn.net/Mark_Chao/article/details/80 ...
- 还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下
Java 8 新特性系列文章索引. Jdk14都要出了,还不能使用 Optional优雅的处理空指针? Jdk14 都要出了,Jdk8 的时间处理姿势还不了解一下? 还看不懂同事的代码?Lambda ...
- 超强的Lambda Stream流操作
原文:https://www.cnblogs.com/niumoo/p/11880172.html 在使用 Stream 流操作之前你应该先了解 Lambda 相关知识,如果还不了解,可以参考之前文章 ...
- 全面吃透JAVA Stream流操作,让代码更加的优雅
全面吃透JAVA Stream流操作,让代码更加的优雅 在JAVA中,涉及到对数组.Collection等集合类中的元素进行操作的时候,通常会通过循环的方式进行逐个处理,或者使用Stream的方式进行 ...
- 深度掌握 Java Stream 流操作,让你的代码高出一个逼格!
概念 Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选.排序.聚合等. Stream 的操作符大体上分为两种:中间操作符和终止操作符 中 ...
- Node学习笔记(一):stream流操作
NodeJs中谈及较多的可能就是Stream模块了,先写一个简单的ajax回调 $.post("index.php",{data:'aaa',order:'ccc'},functi ...
- Stream 流操作
Stream 类 先看下面的图 Stream 是所有流的抽象基类(不能被实例化,需要使用他的派生类FileStream/MemoryStream/BufferedStream).流是字节序列的抽象概 ...
- stream流操作List工具类
工作中操作List对于程序猿来说是"基本操作",为了更加便利,对JDK8的新特性stream流进行二次封装.话不多说,直接上代码 package com.mydemo; impor ...
- .net System.IO.Stream 流操作类(FileStream等)
Stream 是所有流的抽象基类.流是字节序列的抽象概念. 流涉及到的3个基本操作: 读取流,读取是指从流到数据结构(如字节数组)的数据传输. 写入流,写入是指从数据结构到流的数据传输. 流查找,查找 ...
随机推荐
- 目标追踪(Object Tracking)概念的简要介绍
现在我们有一个视频流,可以拆解出 N 个帧出来,这时候初始帧/某一帧中出现了一个我们感兴趣目标,我们希望在后续帧中对这个目标进行追踪,这时候就需要 CV 中的目标追踪: 目标追踪的效果如下: 虽然效果 ...
- 基于伪分布式Hadoop搭建Hive平台详细教程
一.搭建环境的前提条件 环境:Linux系统 Hadoop-2.6.0 MySQL 5.6 apache-hive-2.3.7 这里的环境不一定需要和我一样,基本版本差不多都ok的,所需安装包和压缩包 ...
- 焦大翻译:提防一些seo错误认知(完整版)
http://www.wocaoseo.com/thread-179-1-1.html 多人在开始做seo的时候,都曾经尝试通过黑盒测试来找出哪些因素对排名有效果. 黑盒测试是我们IT行业常用术语,它 ...
- CKA认证经验贴(认证日期:20200817)
一.背景 由于年初疫情影响,身处传统IT行业且兼职出差全国各地“救火”的我有幸被领导选中调研私有云平台,这就给我后来的认证之路做下了铺垫.之前调研kubernetes的v1.17版本自带kubeadm ...
- Python开发的入门教程(六)-函数
介绍 本文主要介绍Python中函数的基本知识和使用 Python之什么是函数 我们知道圆的面积计算公式为: S = πr² 当我们知道半径r的值时,就可以根据公式计算出面积.假设我们需要计算3个不同 ...
- Python 爬虫+tkinter界面 实现历史天气查询
文章目录 一.实现效果 1. python代码 2. 运行效果 二.基本思路 1. 爬虫部分 2. tkinter界面 一.实现效果 很多人学习python,不知道从何学起.很多人学习python,掌 ...
- myblogplus 第三期 如何更改你博客的图标,已实现 - mooling原创
三言两语 博客的logo可以凸显你的blog的个性 不知道你有没有觉得博客园原始的那个小矿工不好看了呢 fromto 这才是个人博客的style! 为什么要写这篇文章 因为在博客园的“找找看”中,如果 ...
- ACwing 你能回答这些问题吗(线段树求最大连续字段和)
给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 maxx≤l≤r≤ymaxx≤l≤r≤y{∑ri=lA[i]∑i=l ...
- 二.spring boot第一个web服务
通过<一.spring boot初始化项目>我们已经会初始化spring boot项目,那本篇文章就说明下初始化项目的具体内容,并编写第一个Hello页面. 项目结构 mvnw.mvnw. ...
- 微信小程序实现滚动视频自动播放(未优化)
先看看大概效果 1.首先需要了解微信API: wx.createIntersectionObserver(Object component, Object options) 创建并返 ...