Stream是什么
Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。原始版本的 Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。
很多流操作本身就会返回一个流,所以多个操作可以直接连接起来。
Stream方法
1、stream()
将集合转换为流
1
2
List<String> list = Arrays.asList("Army", "Luna", "Elle", "Katherine");
Stream<String> stream = list.stream();
2、filter(T -> boolean)
保留lambda结果为true的元素
1
2
3
list = list.stream()
.filter(name -> name.length() > 4)
.collect(toList());
3、distinct()
去除重复元素,以类的equals方法作为判据
1
2
3
list = list.stream()
.distinct()
.collect(toList());
4、sorted() / sorted((T, T) -> int)
如果流中的元素的类实现了 Comparable 接口,即有自己的排序规则,那么可以直接调用 sorted() 方法对元素进行排序,如 Stream
否则, 需要调用 sorted((T, T) -> int)
实现 Comparator 接口。
1
2
3
list = list.stream()
.sorted((p1, p2) -> p1.length() - p2.length())
.collect(toList());
5、limit(long n)
返回前n个元素
1
2
3
list = list.stream()
.limit(2)
.collect(toList());
6、skip(long n)
去除前n个元素
1
2
3
list = list.stream()
.skip(2)
.collect(toList());
7、map(T -> R)
将流中的每一个元素T映射为R
1
List<String> newlist = list.stream().map(Person::getName).collect(toList());
8、flatMap(T -> Stream)
flat意思是:展平。把流中的每一个元素T转化为流,再合并为一个流。
1
2
3
4
5
6
7
8
9
List<String> list = new ArrayList<>();
list.add("aaa bbb ccc");
list.add("ddd eee fff");
list.add("ggg hhh iii");
list = list.stream()
.map(s -> s.split(" "))
.flatMap(Arrays::stream)
.collect(toList());
9、anyMatch(T -> boolean)
流中是否有一个元素匹配给定条件。
1
boolean b = list.stream().anyMatch(person -> person.getAge() == 20);
10、allMatch(T -> boolean)
流中所有元素是否都匹配给定条件。
11、noneMatch(T -> boolean)
流中是否没有元素匹配给定条件。
12、findAny() 和 findFirst()
找到任意一个元素;找到第一个元素。
返回的是:**Optional
13、reduce((T, T) -> T) 和 reduce(T, (T, T) -> T)
将流中元素两两组合,最后得到一个元素。组合的方法取决于lambda表达式。
1
2
3
4
5
6
7
8
// 计算年龄总和:
int sum = list.stream()
.map(Person::getAge)
.reduce(0, (a, b) -> a + b);
// 计算年龄总和:
int sum = list.stream()
.map(Person::getAge)
.reduce(0, Integer::sum);
使用reduce(T, (T, T) -> T)方法时,第一个参数为初始值,函数返回值类型为:T
使用reduce((T, T) -> T)方法是,函数返回值为:**Optional
14、count()
计数
15、collect()
收集方法。
1
2
3
4
5
List newlist = list.stream
.collect(toList());
Map<Integer, Person> map = list.stream()
.collect(toMap(Person::getAge, p -> p));
16、forEach()
遍历
数值流
int sum = list.stream().map(Person::getAge).reduce(0, Integer::sum)
有拆装箱成本。
使用数值流可以避免这个问题。
1、流转化为数值流
- mapToInt(T -> int) : return IntStream
- mapToDouble(T -> double) : return DoubleStream
- mapToLong(T -> long) : return LongStream
2、数值流方法
- sum()
- max()
- min()
- average()
- …
3、数值范围
- rangeClosed(1, 100) :[1, 100]
- range(1, 100) :[1, 100)
构建流
1、值创建
- Stream.of(T)
- Stream.of(T…)
- Stream.empty()
1
Stream<String> stream = Stream.of("aaa", "bbb", "ccc");
2、数组创建
- Arrays.stream(T[ ])
- Arrays.stream(int[ ])
- Arrays.stream(double[ ])
- Arrays.stream(long[ ])
1
2
String[] ss = {"Army", "Luna", "Elle", "Katherine"};
Stream<String> stream = Arrays.stream(ss, 1, 3);
3、函数创建
函数创建为无限流。
Stream.iterate(T, UnaryOperator
):在T基础上,依次对每个新生成的T应用函数 Stream.generate(Supplier
) :按函数生成流
1
2
3
4
// 正偶数集的流
Stream.iterate(0, n -> n + 2);
// 随机数
Stream.generate(Math::random);