1.简单使用
Arrays.asList(1, 4, 2, 3, 5, 6, 7, 9, 0, 8)
.stream()
.sorted()// 排序
.filter(x -> x > 3)// 过滤
.forEach(System.out::print);
运行结果:
4,5,6,7,8,9
- Stream(流)和InputStream/OutputStream并没有关系
- Stream提供了很多Lambda表达式方法
- 重点在于对数组的操作
特点:
- Stream不存储数据
- Stream不会修改源数据,无论怎么操作源数据并不会改变
- Stream是单向的,不可以重复使用
- Stream的部分操作是延迟的
- 只要Stream的方法返回的对象是Stream,这些方法就是延迟执行的方法
- 延迟执行的方法,一定要等到一个迫切方法执行的时候,才会执行。一般在Stream流中,一个方法返回的不是Stream,基本就是迫切方法
- Stream可以执行并行操作
2.创建Stream
数组和集合创建Stream流方法不一样
2.1数组创建Stream
一般可以通过:Arrays.stream()
和Stream.of()
int [] ints = new int[]{1,3,4,2,5};
IntStream intStream= Arrays.stream(ints);
intStream.forEach(System.out::print);
运行结果:13425
注意:不能直接把简单数据类型的数组直接作为Stream.of()
的参数
int [] ints = new int[]{1,3,4,2,5};
Stream<int[]>stream= Stream.of(ints);
stream.forEach(System.out::print);```
运行结果为:
`[I@1218025c`
***
```java
Stream<Integer>stream2 = Stream.of(1,3,4,2,5);
stream2.sorted().forEach(System.out::print);
运行结果为:
12345
Stream<Integer>
和IntStream
不是同一个对象
2.2集合创建Stream
集合可以通过:集合对象.stream()
List<Integer>list = (List<Integer>) Arrays.asList(1,2,4,3,5);
Stream<Integer>stream = list.stream();
2.3创建并行Stream
通过集合对象.parallelStream()
List<Integer>list = (List<Integer>) Arrays.asList(1,2,4,3,5);
Stream<Integer>stream = list.parallelStream();
2.4 创建大量数据的Stream
- 初始化一个无限重复字符串的Stream
Stream.generate(()->"Hello World!!!").forEach(System.out::println);
运行结果:
无限打印出Hello World!!!
- 初始化一个有限的数据的Stream
可以通过limit()
方法来限制创建数据的数量
Stream.generate(()->"Hello World !!!").limit(5).forEach(System.out::println);
运行结果:
打印出5个Hello World!!!
2.5创建一个规律数据的Stream
例如,创建一个从开始1到10的数列的Stream
Stream.iterate(1, x -> x +1).limit(10).forEach(System.out::print);
运行结果:12345678910
iterate()
方法中,有两个参数,第一个为初始数据,第二个为一个Operator
接口
Stream.iterate("a", UnaryOperator.identity()).limit(10).forEach(System.out::print);
运行结果:aaaaaaaaaa
UnaryOperator.identity()
自己返回自己
3.Stream常见的操作
- 过滤操作
filter,distinct
- 变换操作
map,flatMap
- 拆分合并流操作
limit,skip,concat,peek
- 排序操作
sorted,unordered
操作符方法内往往需要一个函数式接口
3.1过滤操作
-
filter
例:找出所有开头为大写字母的字符串
Arrays.asList("Abc","Bc","ac","op","IQ")
.stream()
.filter(s->Character.isUpperCase(s.charAt(0)))
.forEach(System.out::println);
运行结果:
Abc Bc IQ
-
distinct
去除重复元素
Arrays.asList("a","c","ac","c","a","b")
.stream()
.distinct()
.forEach(System.out::println);
运行结果:
a c ac b
3.2变换操作
- map
把一种类型的Stream变为另一种类型的Stream,map
方法内需要一个Function
接口,Function<? super String, ? extends String> mapper
例:将字符串全部变为大写
Arrays.asList("hdfa","adfc","aedc","yui")
.stream()
.map(s->s.toUpperCase()+" ,")
.forEach(System.out::print);
运行结果:
HDFA ,ADFC ,AEDC ,YUI ,
- flatMap
flatMap
方法也需要Function
接口,只是Function
接口的泛型不同,Function<? super T, ? extends Stream<? extends R>> mapper
,返回的是Stream
对象
private static void flatMapStream() {
String [] strs1 = {"a","b","c"};
String [] strs2 = {"d","e","f"};
String [] strs3 = {"a","g","h"};
Arrays.asList(strs1,strs2,strs3)
.stream()
.flatMap(str -> Stream.of(str))
.map(s -> s+",")
.forEach(System.out::print);
}
运行结果:
a,b,c,d,e,f,a,g,h,
flatMap
是把高纬度流变为低纬度流。
str1,str2,str3
作为Stream<String[]>
中的元素,可以看做是二维的数组,经过flatMap
变换,Stream<String[]>
就变为了Stream<String>
,由二维变为了一维。
3.3拆分合并流操作
- limit
限制,返回 Stream 的前面 n 个元素
Arrays.asList(1,2,3,4,5)
.stream()
.limit(3)
.forEach(System.out::print);
运行结果:123
- skip
跳过Stream前的n个元素
Arrays.asList(1,2,3,4,5)
.stream()
.skip(2)
.forEach(System.out::print);
运行结果:345
- concat
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
将两个Stream合并成一个,这个方法一次只能用来合并两个Stream,不能一次多个Stream合并。
private static void concatStream() {
Stream<Integer>stream1=Arrays.asList(1,2,3).stream();
Stream<String>stream2=Arrays.asList("a","b","c").stream();
Stream.concat(stream1,stream2).forEach(System.out::print);
}
运行结果:123abc
3.4流的排序
sorted()
方法是个元素相关的方法,和整体的数据有关系。
- sorted(),无参方法
Arrays.asList(3,1,4,5,2)
.stream()
.sorted()
.forEach(System.out::print);
运行结果:123456
使用sorted()
这个方法,要求Stream中的数据必须实现了Comparable
接口
- sorted(Comparator< ? super T > comparator)
例:按照字符串长度进行排序
Arrays.asList("ae","f","gqet","ertyu","zxc")
.stream()
.sorted((s1,s2)-> Integer.compare(s1.length(), s2.length()))
.forEach(System.out::println);
运行结果:
f ae zxc gqet ertyu
若两个字符串长度相同,按照字母顺序排列,可以用Comparator
的thenComparaimg()
Arrays.asList("ae", "f", "gqet", "abcd", "ertyu", "zxc")
.stream()
.sorted(
Comparator.comparing(String::length)
.thenComparing(String::compareTo)
)
.forEach(System.out::println);
运行结果:
f ae zxc abcd gqet ertyu
反转排序:Comparator
的reversed()
//数字
Arrays.asList(2,3,4,1,5)
.stream()
.sorted(Comparator.reverseOrder())
.forEach(System.out::print);
//字符串
Arrays.asList("ae", "f", "gqet", "abcd", "ertyu", "zxc")
.stream()
.sorted(Comparator.comparing(String::length).reversed())
.forEach(System.out::println);
如果Comparator.comparing()
方法中是非方法引用的Lambda表达式,就无法直接使用.reversed()
parallel().sorted()
之后,不能直接使用forEach()
,要使用forEachOrdered()
。并行Stream和sorted()
并不会冲突。
使用forEach()
Arrays.asList(1,4,5,2,3,6,8,9,7)
.stream()
.parallel()
.sorted()
.forEach(System.out::print);
运行结果:378692415
使用forEachOrdered()
:
Arrays.asList(1,4,5,2,3,6,8,9,7)
.stream()
.parallel()
.sorted()
.forEachOrdered(System.out::print);
运行结果:123456789
4.Stream的结果处理
- 遍历
forEach
- 聚合
reduce
- Optional类型
- 收集
collect
4.1聚合reduce
reduce()
可以实现从一组数据中生成一个数据,这个方法有三种形式:
Optional<T> reduce(BinaryOperator<T> accumulator)
T reduce(T identity, BinaryOperator<T> accumulator)
<U> U reduce(U identity,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner)
例:求累加和
Arrays.asList(1,2,3)
.stream()
.reduce((sum,i)-> sum = sum+i)
.ifPresent(System.out::print);
4.2Optional
Optional
是一种容器,可以存储一些值和null
。利用这个类,可以进行null
的判断,能够有效的避免NullPointerException
-
get()
,可以拿到Optional
中的值,没有值则抛出空指针异常 -
isPresent()
,有非空的值,返回true,否则返回false -
ifPresent()
,public void ifPresent(Consumer<? super T> consumer)
这个方法中需要一个Consumer
接口。如果有非空的值,就执行指定的Consumer
的方法来处理这个非空的值;如果为空,则啥都不做
reduce()
操作返回的就是Optional
4.3收集collect
collect()
可以将Stream流转变成集合
List<Integer>list= Arrays.asList(1,2,3,4,5)
.stream()
.filter(i-> i>3)
.collect(Collectors.toList());
list.forEach(System.out :: print);
5.最后
Java8 常见的函数式接口多看看。