操作符
Stream的操作符大体上分为两种:中间操作符和终止操作符
中间操作符
对于数据流来说,中间操作符在执行制定处理程序后,数据流依然可以传递给下一级的操作符。
- map转换操作符,把比如A->B,这里默认提供了转int,long,double的操作符。
- flatmap拍平操作比如把 int[]{2,3,4} 拍平 变成 2,3,4 也就是从原来的一个数据变成了3个数据,这里默认提供了拍平成int,long,double的操作符。
- limit 限流操作,比如数据流中有10个 我只要出前3个就可以使用。
- distint 去重操作,对重复元素去重,底层使用了equals方法。
- filter 过滤操作,把不想要的数据过滤。
- peek 挑出操作,如果想对数据进行某些操作,如:读取、编辑修改等。
- skip 跳过操作,跳过某些元素。
- sorted(unordered) 排序操作,对元素排序,前提是实现Comparable接口,当然也可以自定义比较器。
终止操作符
数据经过中间加工操作,就轮到终止操作符上场了;终止操作符就是用来对数据进行收集或者消费的,数据到了终止操作这里就不会向下流动了,终止操作符只能使用一次。
- collect 收集操作,将所有数据收集起来,这个操作非常重要,官方的提供的Collectors 提供了非常多收集器,可以说Stream 的核心在于Collectors。
- count 统计操作,统计最终的数据个数。
- findFirst、findAny 查找操作,查找第一个、查找任何一个 返回的类型为Optional。
- noneMatch、allMatch、anyMatch 匹配操作,数据流中是否存在符合条件的元素 返回值为bool 值。
- min、max 最值操作,需要自定义比较器,返回数据流中最大最小的值。
- reduce 规约操作,将整个数据流的值规约为一个值,count、min、max底层就是使用reduce。
- forEach、forEachOrdered 遍历操作,这里就是对最终的数据进行消费了。
- toArray 数组操作,将数据流的元素转换成数组。
中间操作符代码示例
map()方法
将Stream中的包装对象用Function函数进行运算,并包装成新的Stream对象
List<Category> list = Lists.newArrayList();
Category category = new Category() {{
setCategoryName("test1");
}};
Category category2 = new Category() {{
setCategoryName("test2");
}};
list.add(category);
list.add(category2);
list.stream().map(Category::getCategoryName).forEach(System.out::println);
运行结果:
flatmap()方法
是将元素拍平拍扁 ,将拍扁的元素重新组成Stream,并将这些Stream 串行合并成一条Stream
Stream.of("a-b-c-d","e-f-i-g-h").map(s -> s.split("-")).forEach(e -> System.out.println(JSON.toJSONString(e)));
Stream.of("a-b-c-d","e-f-i-g-h").flatMap(e-> Stream.of(e.split("-"))).forEach(System.out::println);
运行结果:
limit()方法
限制元素的个数
Stream.of(1,2,3,4,5,6).limit(3).forEach(e->System.out.println(e));
运行结果:
distinct()方法
将根据equals 方法进行判断,如果要对自己自定义的bean 去重,则需要实现自定义(bean 的某个字段去重)去重。
Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1).distinct().forEach(e->System.out.println(e));
运行结果:
filter()方法
对某些元素进行过滤,不符合筛选条件的将无法进入流的下游
Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1).filter(e->e>=5).forEach(e->System.out.println(e));
运行结果:
peek()方法
将元素挑选出来,可以理解为提前消费
list.stream().peek(c -> {c.setCategoryName(c.getCategoryName()+c.getCategoryId());}).forEach(System.out::println);
运行结果:
skip()方法
跳过 元素
Stream.of(1,2,3,4,5,6,7,8,9).skip(4).forEach(e->System.out.println(e));
运行结果:
sorted()方法
排序 底层依赖Comparable 实现
Stream.of(2,1,3,6,4,9,6,8,0).sorted().forEach(e->System.out.println(e));
运行结果:
也可以提供自定义比较器
// 大于'1',等于'0',小于'-1'
list.stream().sorted((c1, c2) -> c1.getCategoryId() > c2.getCategoryId() ? 1 : c1.getCategoryId() == c2.getCategoryId() ? 0 : -1).forEach(System.out::println);
运行结果:
终止操作符代码示例
collect()方法
使用系统提供的收集器可以将最终的数据流收集到List,Set,Map等容器中。
Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
.collect(Collectors.toSet()) //set 容器
.forEach(e -> System.out.println(e));
运行结果:
count()方法
统计数据流中的元素个数,返回的是long 类型
long count = Stream.of("apple", "banana", "orange", "waltermaleon", "grape").count();
System.out.println(count);
运行结果:
findFirst()方法
获取流中的第一个元素
Optional<String> stringOptional = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
.findFirst();
stringOptional.ifPresent(e->System.out.println(e));
运行结果:
noneMatch()方法
数据流中没有一个元素与条件匹配的
boolean result = Stream.of("aa","bb","cc","aa").noneMatch(e->e.equals("aa"));
运行结果:
allMatch和anyMatch()方法
一个是全匹配,一个是任意匹配 和noneMatch 类似
min 和 max()方法
Optional<Integer> integerOptional = Stream.of(0,9,8,4,5,6,-1)
.min((e1,e2)->e1.compareTo(e2));
integerOptional.ifPresent(e->System.out.println(e));
运行结果:
reduce()方法
一个规约操作,所有的元素归约成一个,比如对所有元素求和,乘啊等。
int sum = Stream.of(0,9,8,4,5,6,-1)
.reduce(0,(e1,e2)->e1+e2);
System.out.println(sum);
运行结果:
forEach()方法
对每个数据遍历迭代
forEachOrdered ()方法
用于并行流的情况下进行迭代,能保证迭代的有序性
这里通过并行的方式输出数字
Stream.of(0,2,6,5,4,9,8,-1)
.parallel()
.forEachOrdered(e->{
System.out.println(Thread.currentThread().getName()+": "+e);});
toArray()方法
转成数组,可以提供自定义数组生成器
Stream.of(0,2,6,5,4,9,8,-1).toArray();
四、Collection.stream().forEach() 与 Collection.forEach()区别
Collection.forEach()使用集合的迭代器(如果指定了一个),集合里元素的处理顺序是明确的。Collection.stream().forEach()只是从列表中逐个获取元素,会忽略迭代器。所以处理顺序是不明确的。