JDK1.8新特性——Stream API

摘要:本文主要学习了JDK1.8的新特性中有关Stream API的使用。

部分内容来自以下博客:

https://blog.csdn.net/icarusliu/article/details/79495534

概述

是什么

Stream API(java.util.stream)把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

Stream是JDK1.8中处理集合的关键抽象概念,它可以指定对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简言之,Stream API提供了一种高效且易于使用的处理数据的方式。

操作方式

JDK1.8通过内部迭代来实现对流的处理,一个流式处理可以分为三个部分:转换成流、中间操作、终止操作。

转换成流:将原始数据转换成一个流对象,以便进行后续操作。

中间操作:将原始的Stream转换成另外一个Stream,如filter返回的是过滤后的Stream。

终止操作:产生的是一个结果或者其它的复合操作,如count或者forEach操作。

转换成流

创建空的Stream对象

 Stream stream = Stream.empty();

通过集合类中的stream()方法或者parallelStream()方法创建

 List<String> list = Arrays.asList("a", "b", "c", "d");
Stream stream = list.stream();// 获取串行的Stream对象
Stream parallelStream = list.parallelStream();// 获取并行的Stream对象

通过数组工具类Arrays的stream()方法创建

 String[] arr = {"a", "b", "c", "d"};
Stream<String> stream = Arrays.stream(arr);

通过Stream中的of()方法创建

 Stream stream = Stream.of("test");
Stream stream = Stream.of("a", "b", "c");

通过Stream中的iterate()方法创建有序的Stream

 public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f);

通过Stream中的generate()方法创建无序的Stream

 public static<T> Stream<T> generate(Supplier<T> s);

中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何得处理,而终止操作时一次性全部处理,称为“惰性求值”。

过滤:filter

定义如下:

对Stream对象按指定的Predicate进行过滤,返回的Stream对象中仅包含未被过滤的元素。

 Stream<T> filter(Predicate<? super T> predicate);

代码如下:

 public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 9, 5, 3, 7);
// 同一个流不能用两遍。
Stream<Integer> streamFilter = stream.filter(new Predicate<Integer>() {
// 使用了匿名类,重写了test()方法。
@Override
public boolean test(Integer i) {
if (i > 5) {
return true;
}
return false;
}
});
// 为了看到过滤后的效果,使用了终止操作forEach()进行打印。
streamFilter.forEach(e -> System.out.println(e));
}

运行结果如下:

 9
7

截取:limit

定义如下:

获取指定的前几个元素,组成新的Stream对象返回。

 Stream<T> limit(long maxSize);

代码如下:

 public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 9, 5, 3, 7).limit(2);
// 为了看到过滤后的效果,使用了终止操作forEach()进行打印。
stream.forEach(e -> System.out.println(e));
}

运行结果如下:

 1
9

跳过:skip

定义如下:

跳过指定的前几个元素,使用剩下的元素组成新的Stream返回。

 Stream<T> skip(long n);

代码如下:

 public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 9, 5, 3, 7).skip(2);
// 为了看到过滤后的效果,使用了终止操作forEach()进行打印。
stream.forEach(e -> System.out.println(e));
}

运行结果如下:

 5
3
7

去重:distinct

定义如下:

调用元素的equals()方法比较,返回一个去重后的Stream对象。

 Stream<T> distinct();

代码如下:

 public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 9, 5, 3, 7, 9, 3).distinct();
stream.forEach(e -> System.out.println(e));
}

运行结果如下:

 1
9
5
3
7

排序:sorted

定义如下:

传入一个比较器,返回排序后的Stream对象。

 Stream<T> sorted(Comparator<? super T> comparator);

代码如下:

 public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 9, 5, 3, 7).sorted((m, n) -> m - n);
stream.forEach(e -> System.out.println(e));
}

运行结果如下:

 1
3
5
7
9

映射(一对一):map

定义如下:

将元素转换成其他形式或者提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

 <R> Stream<R> map(Function<? super T, ? extends R> mapper);

代码如下:

 public static void main(String[] args) {
Stream<String> streamStr = Stream.of("aa", "aaa", "a", "aaaaa", "aaaa");
Stream<Integer> streamInt = streamStr.map(e -> e.length());
streamInt.forEach(e -> System.out.println(e));
}

运行结果如下:

 2
3
1
5
4

散射(一对多):flatMap

定义如下:

对原Stream中的所有元素进行操作,每个元素会有一个或者多个结果,然后将返回的所有元素组合成一个统一的Stream并返回。

 <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

代码如下:

 public static void main(String[] args) {
List<String> list = Arrays.asList("aa", "bb");
list.stream().flatMap((e) -> Demo.filterCharacter(e)).forEach(e -> System.out.println(e));
}
public static Stream<Character> filterCharacter(String str){
List<Character> list = new ArrayList<>();
for (Character ch : str.toCharArray()) {
list.add(ch);
}
return list.stream();
}

运行结果如下:

 a
a
b
b

终止操作

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List,Integer,甚至是void。

检查是否匹配所有元素:allMatch

定义如下:

如果所有元素都满足条件,那么返回true,否则返回false。

 boolean allMatch(Predicate<? super T> predicate);

代码如下:

 public static void main(String[] args) {
boolean match = Stream.of("aa11", "bb11", "cc11").allMatch(e -> e.contains("11"));
System.out.println(match);// true
}

检查是否至少匹配一个元素:anyMatch

定义如下:

如果至少有一个元素满足条件,就返回true,否则返回false。

 boolean anyMatch(Predicate<? super T> predicate);

代码如下:

 public static void main(String[] args) {
boolean match = Stream.of("aa11", "bb11", "cc11").anyMatch(e -> e.contains("aa"));
System.out.println(match);// true
}

检查是否没有匹配的元素:noneMatch

如果所有元素都不满足条件,返回true,否则返回false。

定义如下:

 boolean noneMatch(Predicate<? super T> predicate);

代码如下:

 public static void main(String[] args) {
boolean match = Stream.of("aa11", "bb11", "cc11").noneMatch(e -> e.contains("dd"));
System.out.println(match);// true
}

返回第一个元素:findFirst

定义如下:

返回遇到的第一个元素。

 Optional<T> findFirst();

代码如下:

 public static void main(String[] args) {
Optional<String> find = Stream.of("aa11", "bb11", "cc11").findFirst();
System.out.println(find);// Optional[aa11]
}

返回任意一个元素:findAny

定义如下:

返回处理最快的那个元素。

 Optional<T> findAny();

代码如下:

 public static void main(String[] args) {
Optional<String> find = Stream.of("aa11", "bb11", "cc11").findAny();
System.out.println(find);// Optional[aa11]
}

返回元素个数:count

定义如下:

 long count();

代码如下:

 public static void main(String[] args) {
long count = Stream.of("aa11", "bb11", "cc11").count();
System.out.println(count);//
}

返回元素最大值:max

定义如下:

 Optional<T> max(Comparator<? super T> comparator);

代码如下:

 public static void main(String[] args) {
Optional<String> max = Stream.of("aa11", "bb11", "cc11").max((m, n) -> m.hashCode() - n.hashCode());
System.out.println(max);// Optional[cc11]
}

返回元素最小值:min

定义如下:

 Optional<T> min(Comparator<? super T> comparator);

代码如下:

 public static void main(String[] args) {
Optional<String> max = Stream.of("aa11", "bb11", "cc11").min((m, n) -> m.hashCode() - n.hashCode());
System.out.println(max);// Optional[aa11]
}

规约元素:reduce

定义如下:

可以将流中元素反复结合起来,得到一个值,包含T类型的identity,返回T类型的值。

 T reduce(T identity, BinaryOperator<T> accumulator);

可以将流中元素反复结合起来,得到一个值,返回Optional类型的值。

 Optional<T> reduce(BinaryOperator<T> accumulator);

代码如下:

 public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Integer sumWith0 = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(sumWith0);//
Integer sumWith5 = list.stream().reduce(5, (x, y) -> x + y);
System.out.println(sumWith5);//
Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
System.out.println(sum);// Optional[15]
}

收集元素:collect

定义如下:

将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法。

Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map)。但是Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例。

 <R, A> R collect(Collector<? super T, A, R> collector);

代码如下:

 public static void main(String[] args) {
List<Integer> list = Arrays.asList("aaa", "aa", "aaaaa", "a", "aaaaaa").stream().map(String::length).collect(Collectors.toList());
list.forEach(System.out::println);
}

JDK1.8新特性——Stream API的更多相关文章

  1. Java8 新特性 Stream() API

    新特性里面为什么要加入流Steam() 集合是Java中使用最多的API,几乎每一个Java程序都会制造和处理集合.集合对于很多程序都是必须的,但是如果一个集合进行,分组,排序,筛选,过滤...这些操 ...

  2. java8新特性——Stream API

    Java8中有两大最为重要得改变,其一时Lambda表达式,另外就是 Stream API了.在前面几篇中简单学习了Lambda表达式得语法,以及函数式接口.本文就来简单学习一下Stream API( ...

  3. Java8新特性 - Stream API

    Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找.过滤和映射数据等操作.使用Stream API对集合进行操作,就类似与使用SQL执行的数据库 ...

  4. Java8 新特性 Stream Api 之集合遍历

    前言 随着java版本的不断更新迭代,java开发也可以变得甜甜的,最新版本都到java11了,但是后面版本也是不在提供商用支持,需要收费,但是java8 依然是持续免费更新使用的,后面版本也更新很快 ...

  5. Java 8新特性--Stream API

    Java 8 API添加了一个新的抽象称为流Stream,以一种声明的方式处理数据,可以极大提高程序员的生产力,写出高效.干净.简洁的代码.这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可 ...

  6. JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用

    jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default   Lambda表达式     L ...

  7. JDK1.8新特性之Stream类初识

    JDK1.8新特性之Stream类初识 import java.util.Arrays; import java.util.List; import java.util.Optional; impor ...

  8. JDK1.8 新特性

    jdk1.8新特性知识点: Lambda表达式 函数式接口 *方法引用和构造器调用 Stream API 接口中的默认方法和静态方法 新时间日期API https://blog.csdn.net/qq ...

  9. JDK1.8新特性之(三)--函数式接口

    在上一篇文章中我们介绍了JDK1.8的新特性有以下几项. 1.Lambda表达式 2.方法引用 3.函数式接口 4.默认方法 5.Stream 6.Optional类 7.Nashorm javasc ...

随机推荐

  1. CODING 2.0:如何通过设计给品牌创造价值?

    升级背景 伴随着 CODING 理念的全面升级,CODING 正构建起覆盖构想到交付的全覆盖工具链,用户注册即可实践敏捷开发与 DevOps,提升软件交付质量与速度. 一直以来,CODING 作为软件 ...

  2. apache jmeter 使用

    ======================= 插件 ======================= 在JMeter 中很多东西都是基于插件技术的, 所以扩展性非常好, 比如下面这些东西都是插件: 1 ...

  3. index-css-添加类-移除类-toggleClass-attr

    1=>index()会返回当前元素在所有的兄弟元素里面的索引值用法:$("a").click(function(){ console.log($(this).index()) ...

  4. 【BZOJ1443】[JSOI2009]游戏Game(二分图+博弈)

    BZOJ 题意: 给出一个\(n*m\)的网格,其中有一些障碍点. 现在两个人玩游戏,首先先手选定一个点,然后从后手开始轮流移动,不能移动者即输掉这次游戏. 规定不能移动到那些之前已经到过的格子上. ...

  5. 初学JavaScript正则表达式(八)

    JavaScript正则贪婪模式与非贪婪模式 贪婪模式: 例: \d{3,6} 匹配数字3到6次(正则表达式默认为贪婪模式,即匹配最多次,失败即停) '12345678'.replace(/\d{3, ...

  6. StringBuild

    * StringBuild 初始容量是 32 * 1.属性: * Length:现有内容长度: * Capacity:StringBuild当前最大容量 * * 2. * 通过 设置Length=10 ...

  7. jdoj 2171: Grape

    jdoj 2171: Grape 题意 题目大意 一个农场的葡萄架上挂着n串葡萄,若取一个葡萄就会获得与其相应的美味值.对于连续的k串葡萄,最多取b串,最少取a串, 问能够获得的最大美味值为多少 数据 ...

  8. c# 第40节 密封类、密封方法

    本节内容: 1:密封的存在意义 2:密封方法的实现 1:密封的存在意义 2:密封方法的实现 class2::父类 class Class2 { public virtual void show() { ...

  9. (转)cube-ui后编译

    转载地址:https://www.jianshu.com/p/189755f9ce43 1. 后编译介绍 目前大部分的前端项目开发都是使用es6+的代码并且使用babel进行编译,而传统的对代码包的引 ...

  10. 环形链表 II

    给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 pos 是 - ...