JAVA8 lambda表达式权威教程!
Java 8新特性----Stream流
jdk8是Java 语言开发的一个主要版本,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等等。今天就重点介绍一个非常重要得特性之一 lambda表达式
一:什么是 Stream?
Stream(流)是一个来自数据源的元素队列并支持聚合操作
Java中的Stream并不会存储元素,而是按需计算。 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。 和以前的Collection操作不同,Stream操作还有两个基础的特征如下:
Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格。 这样做可以对操作进行优化, 比如延迟执行和短路。
内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫>做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
二:Stream API 使用
1:使用Stream步骤:
(1)先产生一个流(Stream)一个数据源,获取一个流。
(2)中间链式操作 一个中间的操作链,对数据源的数据进行处理。
(3)产生一个新流:一个终止操作,执行中间操作,产生结果。
注意:Stream操作是延迟执行,他们会等需要结果的时候才会执行。
总结:
中间操作常用方法有:筛选:filter 映射:map 排序:sorted提取与组合 收集:collect。
终止操作:遍历:foreach 匹配:find、match 规约:reduce 聚合:max、min、count。
2:创建Stream的方法的4种方式
【1】Collection接口中的方法:
default Stream<E> stream() 获取串行流
default Stream<E> parallelStream() 获取并行流
案例:
//方式1:Collection接口的方法
Collection collection = new ArrayList();
Stream stream = collection.stream();
Stream stream1 = collection.parallelStream();
//方式2:通过Arrays中的Stream方法 数组
IntStream stream2 = Arrays.stream(new int[]{1, 2, 3, 4, 5});
//方式3:Stream中的of方法
Stream<String> stream3 = Stream.of("111", "222", "333");
//方法4:Stream中的方法 创建无限流 (结果是无线个)
Stream<Integer> iterate = Stream.iterate(2, (x) -> x + 2);
3:中间操作
1:筛选与切片
① Stream filter(Predicate<?super T> predicate)返回由与此给定谓词匹配的此流的元素组成的流。 --->接收Lambda,从流中排除某些元素。
//1:创建Stream;
Stream<Student> stream = list.stream();
//2:filter方法(找到年龄大于等于18岁的学生)
Stream<Student> studentStream = stream.filter((student) -> student.getAge() >= 18);
//3:终止操作;如果没有终止操作的话,上面的第二步中间操作不执行
studentStream.forEach(System.out::println);
/**
* 注意:如果值执行1,2操作的话,不会有任何结果。
* 验证出Steam操作是延迟的,只有进行了终止操作,才会执行中间操作!这就是所谓的延迟加载
*/
②Stream limit(Long maxSize) 返回由该流的元素组成的流,截断长度不能超过maxSize. 只有找到maxSize个满足条件的即可。 ---->截断流,使其元素不超过给定的数量。
public void limitTest02() {
//Limit方法 短路(效率增高),只要找到了2个满足条件的,后面的迭代操作就不在执行了!
list.stream().filter(x -> {
System.out.println("正在过滤!!");
return x.getAge() > 18;
}).limit(2).forEach(System.out::println);
}
③Stream skip(Long n) 在丢掉流的第一个n元素后,返回由该流的n元素组成的流,如果此流包含少于n元素,那么将返回一个空流。 ---->跳过元素,返回一个扔掉了前n个元素的流。 如果流中的元素不足n个,则返回一个空流,与limit(n)互补。
public void skipTest03() {
//skip 方法跳过前2个满足条件的 留下后面满足条件的结果!!
list.stream().filter(x -> {
System.out.println("正在过滤后面满足条件的结果");
return x.getAge() > 18;
}).skip(2).forEach(System.out::println);
}
④Stream distinct()
注意: 自定义的类在去重的过程中必须重新hashCode和equals方法,因为distinct实现的时候底层去找这两个方法。
public void distinctTest04() {
//distinct 去重操作!
list.stream().distinct().forEach(System.out::println);
}
⑤ map映射:
如果需要将流中的元素映射到另一个流中,可以使用map方法。方法签名: Stream map(Function<? super T, ? extends R> mapper); 该接口需要一个Function函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。 Stream流中的map方法基本使用的代码如:
@Test
public void testMap() {
Stream<String> original = Stream.of("11", "22", "33");
Stream<Integer> result = original.map(Integer::parseInt);
result.forEach(s -> System.out.println(s + 10));
}
//这段代码中,map方法的参数通过方法引用,将字符串类型转换成为了int类型(并自动装箱为Integer类对象)。
⑥ 排序 (两种方式)
(1)Stream sorted()返回此流元素组成的流,根据自然顺序排序。底层按照内部比较器进行排序,实现Comparable接口中的compareTo方法。
(2)Stream sorted(Comparator<?super T>comparator) 返回由此元素组成的流,根据挺的Comparator进行顺序排序。指定顺序。 指定排序策略:底层按照外部比较器进行排序 Comparator接口一定要重新Compare方法。
基本使用
Stream流中的sorted方法基本使用的代码如:
@Test
public void testSorted() {
// sorted(): 根据元素的自然顺序排序
// sorted(Comparator<? super T> comparator): 根据比较器指定的规则排序
Stream.of(33, 22, 11, 55)
.sorted()
.sorted((o1, o2) -> o2 - o1)
.forEach(System.out::println);
}
这段代码中,sorted方法根据元素的自然顺序排序,也可以指定比较器排序。
4:终止操作
①查找(find)和匹配(match)
如果需要找到某些数据,可以使用find相关方法。方法签名:
- Optional findFirst();
- Optional findAny();
Stream流中的find相关方法使用代码:
@Test
public void testFind() {
Optional<Integer> first = Stream.of(5, 3, 6, 1).findFirst();
System.out.println("first = " + first.get());
Optional<Integer> any = Stream.of(5, 3, 6, 1).findAny();
System.out.println("any = " + any.get());
}
Stream流的match方法
如果需要判断数据是否匹配指定的条件,可以使用Match相关方法。方法签名:
- boolean allMatch(Predicate<? super T> predicate);
- boolean anyMatch(Predicate<? super T> predicate);
- boolean noneMatch(Predicate<? super T> predicate); 基本使用 Stream流中的Match相关方法使用代码如:
@Test
public void testMatch() {
boolean b = Stream.of(5, 3, 6, 1)
// .allMatch(e -> e > 0); // allMatch: 元素是否全部满足条件
// .anyMatch(e -> e > 5); // anyMatch: 元素是否任意有一个满足条件
.noneMatch(e -> e < 0); // noneMatch: 元素是否全部不满足条件
System.out.println("b = " + b);
}
②:遍历 foreach
//forEach 用来遍历流中的数据
@Test
public void test02() {
//案例1、2下面两种写法等同
list.stream().map((x)->x.getName()).forEach(System.out::println);
list.stream().map(Student::getName).forEach(System.out::println);
}
③Stream流的max、min
List<String> list13 = Arrays.asList("zhangsan","lisi","wangwu","xuwujing");
int maxLines = list13.stream().mapToInt(String::length).max().getAsInt();
int minLines = list13.stream().mapToInt(String::length).min().getAsInt();
System.out.println("最长字符的长度:" + maxLines+",最短字符的长度:"+minLines);
//最长字符的长度:8,最短字符的长度:4
④Stream流的count
// Stream流提供count方法来统计其中的元素个数:long count();
//该方法返回一个long值代表元素个数。基本使用:
@Test
public void testCount() {
List<String> strList = new ArrayList<>();
Collections.addAll(strList, "张无忌", "周芷若", "赵敏", "小昭", "杨不悔);
System.out.println(strList.stream().count());
}
⑤ 分组:groupingBy;
当我们使用Stream流处理数据后,可以根据某个属性将数据分组:
// 案例:
@Test
public void testGroup() {
Stream<Student> studentStream = Stream.of(
new Student("赵丽颖", 52, 95),
new Student("杨颖", 56, 88),
new Student("迪丽热巴", 56, 55),
new Student("柳岩", 52, 33));
// Map<Integer, List<Student>> map = studentStream.collect(Collectors.groupingBy(Student::getAge));
// 将分数大于60的分为一组,小于60分成另一组
Map<String, List<Student>> map = studentStream.collect(Collectors.groupingBy((s) -> {
if (s.getSocre() > 60) {
return "及格";
} else {
return "不及格";
}
}));
map.forEach((k, v) -> {
System.out.println(k + "::" + v);
});
}
效果:
不及格::[Student{name='迪丽热巴', age=56, socre=55}, Student{name='柳岩', age=52, socre=33}]
及格::[Student{name='赵丽颖', age=52, socre=95}, Student{name='杨颖', age=56, socre=88}]
⑥拼接:joining
Collectors.joining会根据指定的连接符,将所有元素连接成一个字符串。
// 拼接
@Test
public void testJoining() {
Stream<Student> studentStream = Stream.of(
new Student("赵丽颖", 52, 95),
new Student("杨颖", 56, 88),
new Student("迪丽热巴", 56, 99),
new Student("柳岩", 52, 77));
String collect = studentStream
.map(Student::getName)
.collect(Collectors.joining(">_<", "^_^", "^v^"));
System.out.println(collect);
}
效果:
^_^赵丽颖>_<杨颖>_<迪丽热巴>_<柳岩^v^
⑦聚合:toList,toSet,toMap;
Stream流提供collect方法,其参数需要一个java.util.stream.Collector<T,A, R>接口对象来指定收集到哪种集合中。
- public static Collector<T, ?, List> toList():转换为List集合。
- public static Collector<T, ?, Set> toSet():转换为Set集合。
- public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper):转换为Map集合。
下面是这两个方法的基本使用代码:
// 将流中数据收集到集合中
@Test
public void testStreamToCollection() {
Stream<String> stream = Stream.of("aa", "bb", "cc");
// List<String> strList = stream.collect(Collectors.toList());
// Set<String> strSet = stream.collect(Collectors.toSet());
ArrayList<String> arrayList = stream.collect(Collectors.toCollection(ArrayList::new));
HashSet<String> hashSet = stream.collect(Collectors.toCollection(HashSet::new));
}
toMap
@Test
public void testCollectToMap(){
//案例1
List<Integer> list = Arrays.asList(1, 2, 3);
Map<String, String> collect1 = list.stream().map(i -> i).collect(Collectors.toMap(key -> "key" + key, value -> "value:" + value));
//实体list转化map id作为主键,对象作为value
List<User> userList =new ArrayList<User>();
UserTask userTask = new UserTask();
userTask.setId(1);
userTask.setName("测试");
userList.add(userTask);
Map<Integer,UserTask> taskMap = userList.stream().collect(Collectors.toMap(UserTask::getId, entity -> entity));
System.out.println(collect1.toString());
System.out.println(taskMap.toString());
}
JAVA8 lambda表达式权威教程!的更多相关文章
- java8 Lambda表达式的新手上车指南(1)
背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...
- java8 Lambda表达式的新手上车指南(1)--基础语法和函数式接口
背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...
- Java8 Lambda表达式详解手册及实例
先贩卖一下焦虑,Java8发于2014年3月18日,距离现在已经快6年了,如果你对Java8的新特性还没有应用,甚至还一无所知,那你真得关注公众号"程序新视界",好好系列的学习一下 ...
- Java8 Lambda表达式(一)
目录 一.应用场景引入 优化一:使用策略模式 优化二:使用匿名内部类 优化三:使用Lambda表达式 优化四:使用Stream API 二.Lambda运算符和对应语法 语法格式 Lambda表达式需 ...
- Java8 Lambda表达式、函数式接口和方法引用
目录 Java8 Lambda表达式和函数式接口 Lambda表达式 Lambda的使用 函数式接口FunctionalInterface Java内置四大核心函数式接口 方法引用 构造器引用 Jav ...
- 【Java学习笔记之三十一】详解Java8 lambda表达式
Java 8 发布日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Java 8之前 ...
- java8 快速入门 lambda表达式 Java8 lambda表达式10个示例
本文由 ImportNew - lemeilleur 翻译自 javarevisited.欢迎加入翻译小组.转载请见文末要求. Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发 ...
- Java8 lambda表达式10个示例
Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Ja ...
- Java8 lambda表达式语法 1
本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人也是刚刚开始学习Java8,所以文中肯定有错误和理解偏差的地方,希望大家帮忙指出,我会持续修改和优化.本文是该系列的第一篇, ...
随机推荐
- Azure Cost alerts 费用成本分析
一,引言 依稀记得在一月初,我们在 Azure 上做成了一个 费用警报的监控,果不其然,前两天 Azure 给我发了两封封 Azure 预警警报的邮件,提醒我的预算的总费用超过了设置的通知阈值 &qu ...
- 精通模块化JavaScript
近日读了一本名为<精通模块化JavaScript>的书,并记录了其中的精髓. 一.模块化思维 精通模块化开发并不是指要遵循一套定义明确的规则,而是指能够将自己置身于使用者的角度,为可能即将 ...
- Androidd Studio 之多行文字跑马灯特效
•效果展示图 •参考资料 两种方法实现TextView跑马灯效果(字体横向滚动) •出现的问题 新建 Java 文件继承 TextView 时出现问题: •解决方法 不应该继承 $TextView$ ...
- 基于Hive进行数仓建设的资源元数据信息统计:Spark篇
在数据仓库建设中,元数据管理是非常重要的环节之一.根据Kimball的数据仓库理论,可以将元数据分为这三类: 技术元数据,如表的存储结构结构.文件的路径 业务元数据,如血缘关系.业务的归属 过程元数据 ...
- Database | 浅谈Query Optimization (2)
为什么选择左深连接树 对于n个表的连接,数量为卡特兰数,近似\(4^n\),因此为了减少枚举空间,早期的优化器仅考虑左深连接树,将数量减少为\(n!\) 但为什么是左深连接树,而不是其他样式呢? 如果 ...
- UnitFourSummary
目录 第四单元架构设计 taskOne taskTwo taskThree 四个单元架构设计与OO方法理解的演进 四个单元架构设计 UnitOne UnitTwo UnitThree UnitFour ...
- 原创 Spring Boot 2.3 新特性分层JAR
背景 在我们实际生产容器化部署过程中,往往会遇到 Docker 镜像很大,部署发布很慢的情况 影响 docker 镜像大小的因素,主要有以下三个方面: 基础镜像的大小 .尽量选择 aphine 作为基 ...
- 如何建立一个足够安全的SSH连接?
1 概述 使用SSH连接服务器是一件很平常的事,但是,连接是否足够安全是一个令人担忧的问题.本文从如下几个方面介绍了如何建立一个足够安全的SSH连接: 端口 协议 用户 密码 密钥对 ssh-agen ...
- 次小生成树 详解及模板 (仅kruskal)
思路 关于次小生成树,首先求出最小生成树,然后枚举每条不在最小生成树上的边(在原本的节点上添加一个vis属性进行判断即可),并把这条边放到最小生成树上面,然后就一定会形成环,那么我们在这条环路中取出一 ...
- JAVAEE_Servlet_15_HttpServletRequest中常用方法(二)
HttpServletRequest中常用方法 ## HttpServletRequest中的第二类方法 获取各种路径 和 IP地址 * 获取路径和地址 - 获取ServletContext上下文对象 ...