JAVA 8 Streams
什么是Stream
首先要说的是,不要被它的名称骗了,这里的Stream跟JAVA I/O中的InputStream和OutputStream是两个不同的概念。Java 8中的Stream其实是函数式编程里Monad的概念,关于Monad,感觉还是比较抽象,不好理解,可以参考这篇文章,个人觉得还是比较好看懂的,简单说,Monad就是一种设计模式,表示将一个运算过程,通过函数拆解成互相连接的多个步骤,有点链式操作的感觉。
如下,是一个Stream的例子
import java.util.Arrays;
import java.util.List; public class Snippet
{
public static void main(String[] args)
{
List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1"); myList
.stream()
.filter(s -> s.startsWith("c")) //过滤以c字母开头
.map(String::toUpperCase) //字符变成大写
.sorted() //排序
.forEach(System.out::println); //打印输出
}
}
使用Stream的好处
- 对JAVA集合(Collection)对象功能的增强,方便对集合进行各类操作(过滤、求最大值、最小值、统计等);
- 更加高效,提供串行和并行两种模式,并行模式利用了Java中的fork/join框架技术,能充分利用多核处理器,提高程序并发性;
Stream的特征
- 不是一个数据结构
- 为lambda表达式设计
- 不支持索引访问
- 很方便的作为数组或集合输出
- 支持惰性访问
- 并行计算
如何得到Stream对象
从 Collection 和数组
- Collection.stream()
- Collection.parallelStream()
- Arrays.stream(T array) or Stream.of()
从 BufferedReader
- java.io.BufferedReader.lines()
静态工厂
- java.util.stream.IntStream.range()
- java.nio.file.Files.walk()
自己创建
- java.util.Spliterator
其它
- Random.ints()
- BitSet.stream()
- Pattern.splitAsStream(java.lang.CharSequence)
- JarFile.stream()
- 。。。
Stream的操作类型
Stream有两种类型的操作:Intermediate操作和Terminal操作。
Intermediate(中间操作)
Stream可以进行多次的Intermediate操作,如前面开头的那个例子,其中filter、map、sorted都是Intermediate操作,注意该操作是惰性化的,当调用到该方法的时候,并没有真正开始Stream的遍历。
Terminal(结束操作)
一个Stream只有一个Terminal操作,如前面开头的那个例子,其中forEach就是Terminal操作,Terminal操作是Stream的最后一个操作,这时候才会开始Stream的遍历。
Stream使用示例
Stream的创建
使用Stream.of
import java.util.stream.Stream; public class StreamBuilders
{
public static void main(String[] args)
{
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
stream.forEach(p -> System.out.println(p));
}
}
使用Arrays.stream
import java.util.Arrays;
import java.util.stream.Stream; public class StreamBuilders
{
public static void main(String[] args)
{
Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9});
stream.forEach(p -> System.out.println(p));
}
}
使用Collection.stream() or Collection.parallelStream()
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class StreamBuilders
{
public static void main(String[] args)
{
List<Integer> list =
new ArrayList<Integer>(Arrays.asList(new Integer[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9 })); Stream<Integer> stream = list.stream(); //or list.parallelStream();
stream.forEach(p -> System.out.println(p));
}
}
使用IntStream.range
import java.util.stream.IntStream; public class StreamBuilders
{
public static void main(String[] args)
{
IntStream stream = IntStream.range(1, 9);
stream.forEach(p -> System.out.println(p));
}
}
使用Random.ints()
import java.util.Random;
import java.util.stream.IntStream; public class StreamBuilders
{
public static void main(String[] args)
{
IntStream stream = new Random().ints(1, 10);
stream.forEach(p -> System.out.println(p));
}
}
使用Stream.generate()
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream; public class StreamBuilders
{
static int i = 0;
public static void main(String[] args)
{
Stream<Integer> stream = Stream.generate(() -> {
try
{
TimeUnit.SECONDS.sleep(1);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return i++;
});
stream.forEach(p -> System.out.println(p));
}
}
其它还有很多,这里暂不一一列出。
Stream类型转集合/数组类型
使用stream.collect(Collectors.toList())
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream; public class StreamBuilders
{
public static void main(String[] args)
{
List<Integer> list =
new ArrayList<Integer>(Arrays.asList(new Integer[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9 })); Stream<Integer> stream = list.stream(); List<Integer> evenNumbersList = stream.filter(i -> i % 2 == 0).collect(Collectors.toList()); System.out.print(evenNumbersList);
}
}
使用stream.toArray(EntryType[]::new)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class StreamBuilders
{
public static void main(String[] args)
{
List<Integer> list =
new ArrayList<Integer>(Arrays.asList(new Integer[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9 })); Stream<Integer> stream = list.stream(); Integer[] evenNumbersArr = stream.filter(i -> i % 2 == 0).toArray(Integer[]::new); System.out.print(Arrays.asList(evenNumbersArr));
}
}
其它转为set,map的类似,不一一列出。
Stream核心操作方法
Intermediate(中间操作),这里只列出常见的几个
filter方法,过滤元素
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class StreamBuilders
{
public static void main(String[] args)
{
List<String> list = new ArrayList<String>(Arrays.asList(new String[]{
"Amitabh", "Shekhar", "Aman", "Rahul",
"Shahrukh", "Salman", "Yana", "Lokesh"})); Stream<String> stream = list.stream(); stream.filter((s) -> s.startsWith("A")).forEach(System.out::println);
}
}
map方法,修改元素
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class StreamBuilders
{
public static void main(String[] args)
{
List<String> list = new ArrayList<String>(Arrays.asList(new String[]{
"Amitabh", "Shekhar", "Aman", "Rahul",
"Shahrukh", "Salman", "Yana", "Lokesh"})); Stream<String> stream = list.stream(); stream.filter((s) -> s.startsWith("A")).map(String::toUpperCase).forEach(System.out::println);
}
}
sorted方法,排序,可以传入自定义排序接口Comparator,
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class StreamBuilders
{
public static void main(String[] args)
{
List<String> list = new ArrayList<String>(Arrays.asList(new String[]{
"Amitabh", "Shekhar", "Aman", "Rahul",
"Shahrukh", "Salman", "Yana", "Lokesh"})); Stream<String> stream = list.stream(); stream.sorted().map(String::toUpperCase).forEach(System.out::println);
}
}
Terminal(结束操作),这里只列出常见的几个
这里的例与前面的类似,就不写出全部代码了,列出重要部分。
forEach方法,迭代元素,并执行相关操作
stream.sorted().map(String::toUpperCase).forEach(System.out::println);
collect方法,从Stream中得到集合
List<String> memNamesInUppercase = stream.sorted().map(String::toUpperCase).collect(Collectors.toList()); System.out.print(memNamesInUppercase);
Match方法,匹配判断Stream中的元素是否符合指定规则
boolean matchedResult = list.stream().anyMatch((s) -> s.startsWith("A")); System.out.println(matchedResult); matchedResult = list.stream().allMatch((s) -> s.startsWith("A")); System.out.println(matchedResult); matchedResult = list.stream().noneMatch((s) -> s.startsWith("A")); System.out.println(matchedResult);
count方法,计数
long totalMatched = list.stream().filter((s) -> s.startsWith("A")).count(); System.out.println(totalMatched);
reduce方法,元素组合操作,常用于字符串拼接、数值的 sum、min、max、average
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional; public class StreamBuilders
{
public static void main(String[] args)
{
List<String> list = new ArrayList<String>(Arrays.asList(new String[]{
"Amitabh", "Shekhar", "Aman", "Rahul",
"Shahrukh", "Salman", "Yana", "Lokesh"})); Optional<String> reduced = list.stream().reduce((s1, s2) -> s1 + "#" + s2); reduced.ifPresent(System.out::println); //打印结果:Amitabh#Shekhar#Aman#Rahul#Shahrukh#Salman#Yana#Lokesh
}
}
Stream短路操作
所谓的短路操作。指的是如果符合要求的话,就不继续执行接下来的操作,类似于&&和||操作,
在Stream中,类似的有anyMatch()和findFirst()方法,
anyMatch(),返回布尔值,只要找到一个匹配的元素,就停止接下来的元素遍历;
boolean matched = list.stream().anyMatch((s) -> s.startsWith("A")); System.out.println(matched); // Output: true
findFirst(),返回元素,同样,只返回第一个元素,不会全部遍历;
String firstMatchedName = list.stream().filter((s) -> s.startsWith("L")).findFirst().get(); System.out.println(firstMatchedName); // Output: Lokesh
并发parallelStream
Java 7引入了Fork/Join并行计算框架,能让我们以并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。
如下示例:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream; public class StreamBuilders
{
public static void main(String[] args)
{
List<Integer> list =
new ArrayList<Integer>(Arrays.asList(new Integer[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9 })); // Here creating a parallel stream
Stream<Integer> stream = list.parallelStream();
Integer[] evenNumbersArr = stream.filter(i -> i % 2 == 0).toArray(Integer[]::new);
System.out.print(Arrays.asList(evenNumbersArr));
}
}
使用Stream与不用Stream对比
下面给出一个使用Stream与不使用Stream示例,用于统计字符长度为3的字符串个数。
import java.util.Arrays;
import java.util.List; public class Java8Tester {
public static void main(String args[]){ List<String> strings = Arrays.asList("abc", "111", "bc", "efg", "12584","", "1254"); //使用Java 7, 统计字符长度为3的字符串个数
long count = 0;
for(String string: strings){ if(string.length() == 3){
count++;
}
}
System.out.println("using java7:Strings of length 3: " + count); //使用Java 8的stream, 统计字符长度为3的字符串个数
count = strings.stream().filter(string -> string.length() == 3).count();
System.out.println("using java8:Strings of length 3: " + count); }
}
参考资料
http://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/
http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/
https://www.tutorialspoint.com/java8/java8_streams.htm
http://howtodoinjava.com/core-java/collections/java-8-tutorial-streams-by-examples/
JAVA 8 Streams的更多相关文章
- Understanding Java 8 Streams API---reference
http://java.amitph.com/2014/01/understanding-java-8-streams-api.html Since past few versions, Java h ...
- Java 8 Streams的简单使用方法
Java 8 Streams的简单使用方法 package JDK8Test; import java.util.ArrayList; public class Main { public stati ...
- List遍历Java 8 Streams map() examples
1. A List of Strings to Uppercase 1.1 Simple Java example to convert a list of Strings to upper case ...
- Java 8 Streams filter examples
1. Streams filter() and collect() package com.mkyong.java8; import java.util.Arrays;import java.util ...
- Java 8 Streams API 详解
流式编程作为Java 8的亮点之一,是继Java 5之后对集合的再一次升级,可以说Java 8几大特性中,Streams API 是作为Java 函数式的主角来设计的,夸张的说,有了Streams A ...
- java 8 Streams简介
目录 简介 Functional Interface Function:一个参数一个返回值 BiFunction:接收两个参数,一个返回值 Supplier:无参的Function Consumer: ...
- Java 8 Learn Notes - Streams
Main reference [1] http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples 1. How Stream ...
- Java资源大全中文版(Awesome最新版)
Awesome系列的Java资源整理.awesome-java 就是akullpp发起维护的Java资源列表,内容包括:构建工具.数据库.框架.模板.安全.代码分析.日志.第三方库.书籍.Java 站 ...
- JAVA中的Fork/Join框架
看了下Java Tutorials中的fork/join章节,整理下. 什么是fork/join框架 fork/join框架是ExecutorService接口的一个实现,可以帮助开发人员充分利用多核 ...
随机推荐
- 学习SpringMVC——从HelloWorld开始
前言: 时隔十二年,中国女排最终过关斩将,用3:1的成绩证明了自己的实力,霸气夺冠,为中国赢得了一枚意义非常的金牌.这是一次全民的狂欢,一场视听盛宴,带给我们不仅是熠熠生辉的金牌,更传递出的是一种女排 ...
- 体验了微信小程序,发现安卓用户终于把果粉“碾压”了一次
今天早上,张小龙在微信公开课上分享了小程序的理念,并且公布了小程序将于1月9日上线. 为了体现张小龙对未来程序形态的理解,小程序有四个特定:无需安装.触手可及.用完即走.无需卸载.今天,36氪刚好有机 ...
- JavaScript字符串排序localeCompare()笔记
今天遇到了一个没有接触过的方法,是localeCompare().查了一些相关的文档,给出的定义很模糊,所以就把自己的理解写下来. 首先由例子入手! 已知一串学生姓名的字符串,根据学生姓名的长度按照降 ...
- Apache Spark源码剖析
Apache Spark源码剖析(全面系统介绍Spark源码,提供分析源码的实用技巧和合理的阅读顺序,充分了解Spark的设计思想和运行机理) 许鹏 著 ISBN 978-7-121-25420- ...
- Android笔记——permission权限大全
访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permiss ...
- [C#] Socket 通讯,一个简单的聊天窗口小程序
Socket,这玩意,当时不会的时候,抄别人的都用不好,简单的一句话形容就是“笨死了”:也是很多人写的太复杂,不容易理解造成的.最近在搞erlang和C的通讯,也想试试erlang是不是可以和C#简单 ...
- 应用Web.Config配置网站
1.配置数据库连接 在ASP.NET中配置数据库连接的两种方式: appSettings和connectionStrings 命名空间: using System.Configuration; 1)a ...
- Sql Server系列:索引基础
1 索引概念 索引用于快速查找在某个列中某个特定值的行,不使用索引,数据库必须从第1条记录开始读完整个表,知道找出需要的行.表越大,查询数据所花费的时间越多.如果表中查询的列有索引,数据库能快速到达一 ...
- Java设计模式之单例模式(Singleton)
前言: 在总结okHttp的时候,为了管理网络请求使用到了单例模式,晚上实在没啥状态了,静下心来学习总结一下使用频率最高的设计模式单例模式. 单例模式: 单例模式确保某个类只有一个实例,而且自行实例化 ...
- IOS数据存储之FMDB数据库
前言: 最近几天一直在折腾数据库存储,之前文章(http://www.cnblogs.com/whoislcj/p/5485959.html)介绍了Sqlite 数据库,SQLite是一种小型的轻量级 ...