转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/106389071
本文出自【赵彦军的博客】
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
如果你用过 rxjava ,入门就很简单。
var list = mutableListOf("b", "a", "d", "c")
ist.stream()
.filter {
it != "a" //输出元素不是 a 的元素
}
.forEach {
Log.d("yanjun", it)
}
输出结果:
D/yanjun: b
D/yanjun: d
D/yanjun: c
var list = mutableListOf("b", "a", "d", "c")
var first = list.stream()
.findFirst() //查找第一个元素
.get()
Log.d("yanjun", first)
输出结果:
D/yanjun: b
var list2 = listOf(3, 1, 2)
list2.stream()
.sorted() //默认从小到大排序
.forEach {
Log.d("yanjun", it.toString())
}
输出结果:
D/yanjun: 1
D/yanjun: 2
D/yanjun: 3
var list = listOf(3, 1, 2)
list.stream()
.map {
it * 2 //所有元素都乘以 2
}
.forEach {
Log.d("yanjun", it.toString())
}
输出结果:
D/yanjun: 6
D/yanjun: 2
D/yanjun: 4
var list = listOf(3, 1, 2)
list.stream()
.limit(2) //只输出前2个数据
.forEach {
Log.d("yanjun", it.toString())
}
输出结果:
D/yanjun: 3
D/yanjun: 1
var list = listOf(3, 1, 2)
var list2 = list.stream()
.sorted() //排序 结果为:1 2 3
.collect(Collectors.toList()) //把流数据转换成 list
list2.forEach {
Log.d("yanjun", it.toString())
}
输出结果:
D/yanjun: 1
D/yanjun: 2
D/yanjun: 3
var list = listOf(3, 1, 2)
var value = list.average() //求平均值
Log.d("yanjun", value.toString())
输出结果:
D/yanjun: 2.0
数据流的链式调用是垂直执行的, 但并不是每个操作符都是垂直的,sorted是水平执行的。
为什么要设计成这样呢?原因是出于性能的考虑。
var list = mutableListOf("b", "a", "d", "c")
list.stream()
.map {
Log.d("yanjun map", it)
it
}
.forEach {
Log.d("yanjun forEach", it)
}
输出结果:
D/yanjun map: b
D/yanjun forEach: b
D/yanjun map: a
D/yanjun forEach: a
D/yanjun map: d
D/yanjun forEach: d
D/yanjun map: c
D/yanjun forEach: c
var list = mutableListOf("b", "a", "d", "c")
list.stream()
.map {
Log.d("yanjun map", it)
it
}
.sorted() //排序
.forEach {
Log.d("yanjun forEach", it)
}
输出结果:
D/yanjun map: b
D/yanjun map: a
D/yanjun map: d
D/yanjun map: c
D/yanjun forEach: a
D/yanjun forEach: b
D/yanjun forEach: c
D/yanjun forEach: d
Java8 Stream 流是不能被复用的,一旦你调用任何终端操作,流就会关闭:
var list = mutableListOf("b", "a", "d", "c")
var stream = list.stream()
//流第一次被使用,使用完毕后,流被关闭,不能重复使用
stream.forEach {
Log.d("yanjun", it)
}
//流第二次被使用,会报异常
stream.forEach {
Log.d("yanjun", it)
}
集合支持parallelStream()方法来创建元素的并行流。或者你可以在已存在的数据流上调用中间方法parallel(),将串行流转换为并行流,这也是可以的。
var list = mutableListOf("b", "a", "d", "c")
list.parallelStream() //创建并行流
.map {
Thread.sleep(5000) //模拟耗时操作
Log.d("yanjun map", Thread.currentThread().name + " " + it)
it
}
.forEach {
Log.d("yanjun forEach", Thread.currentThread().name + " " + it)
}
输出结果:
D/yanjun map: main d
D/yanjun forEach: main d
D/yanjun map: ForkJoinPool.commonPool-worker-1 a
D/yanjun map: ForkJoinPool.commonPool-worker-2 b
D/yanjun forEach: ForkJoinPool.commonPool-worker-1 a
D/yanjun forEach: ForkJoinPool.commonPool-worker-2 b
D/yanjun map: ForkJoinPool.commonPool-worker-3 c
D/yanjun forEach: ForkJoinPool.commonPool-worker-3 c
如您所见,并行流使用了所有的ForkJoinPool中的可用线程来执行流式操作。在持续的运行中,输出结果可能有所不同,因为所使用的特定线程是非特定的。