简单来说,Stream就是java中用来模拟流数据的一种方式,它不是一种数据结构,也不是i一中内部存储,只负责抓去数据,也不会变更底层数据。提供的一些方法可以模拟sql进行快速的数据处理,也可以类比为大数据中的MR处理,和scala中的算子有着异曲同工的意思。
Stream有一个特性,就是内部方法操作必须使用lambda表达式。
实例化一个Stream对象有几种方式
Stream<String> stream1 = Stream.of("string", "int", "double", "long");
Stream.of()方法也可以直接把数组传进去
String[] str = {"boolean", "map", "array"};
Stream<String> stream2 = Stream.of(str);
Stream.of()内部其实调用的是Arrays类中的一个方法,具体源码如下:
@SafeVarargs
@SuppressWarnings("varargs") // Creating a stream from an array is safe
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
因为Stream.of()是调用的Arrays.stream(),那么这个方法也可以返回一个Stream类的对象
Stream<String> stream3 = Arrays.stream(str);
集合类型可以调用stream()方法返回一个Stream对象
List<String> list = Arrays.asList("struct", "float");
Stream<String> stream4 = list.stream();
数组可以通过Stream.of()转换为Stream
list可以通过stream()转换为Stream
Stream可以通过collect()转换为其他类型
转换为list或者set
List<String> list1 = stream1.collect(Collectors.toList());
Set<String> set1 = stream1.collect(Collectors.toSet());
List<String> list2 = stream1.collect(Collectors.toCollection(ArrayList :: new));
转换为string
String str2 = stream1.collect(Collectors.joining());
注意:每个stream只能使用1次,佛则会有非法状态的异常
java.lang.IllegalStateException: stream has already been operated upon or closed
拿集合举例,如果要过滤一个集合中的元素,传统应该怎么做?
for (String s : list) {
if (!"string".equals(s)){
System.out.println(s);
}
}
使用Stream流时候
stream1.filter(str -> !"string".equals(str)).collect(Collectors.toList()).forEach(System.out::println);
除此之外,如果没有找到,还可以配合findAny和orElse方法处理
System.out.println(stream1.filter("string"::equals).findAny().orElse("无过滤"));
还可以配合mapToInt和sum进行计算
Stream<Integer> streamInt = Stream.of(1, 2, 3, 4);
int res = streamInt.filter(num -> num > 2).mapToInt(n -> n).sum();
map的使用就是做基本转换
比如:全部转换为大写
stream1.map(str -> str.toUpperCase()).collect(Collectors.toList()).forEach(System.out::println);
比如:转换为长度
stream1.map(str -> str.length()).collect(Collectors.toList()).forEach(System.out::println);
扁平化处理,可以对元素进行打散操作
List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
stream.collect(Collectors.toList()).forEach(System.out::println);
还可以配合其他的处理,比如filter,过滤出带有“ , ”的字符串
List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
stream.filter(str -> str.matches(".*,.*")).forEach(System.out::println);
如果是模拟sql,那么limit是必不可少的
ist<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
stream.limit(2).forEach(System.out::println);
只输出两个结果,limit方法是取前n个数据,那么skip是去除前n个数据,那么两个可以一同使用
List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
stream.limit(2).skip(1).forEach(System.out::println);
有了limit,那怎么能少了sort呢,sort就是排序了
List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
stream.sorted().forEach(System.out::println);
如果不指定排序方式,会默认升序排序
List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
stream.sorted((a,b) -> -(a.length()-b.length())).forEach(System.out::println);
peek会对每个元素执行操作并返回一个新的Stream
List<String> list2 = Arrays.asList("hello world, the first day, happy", "hi baidu, hi aliyun");
Stream<String> stream = list2.stream().flatMap(str -> Stream.of(str.split(" ")));
stream.filter(str -> str.length()>5).peek(ele -> System.out.print(ele + " --> "))
.map(String::toUpperCase).peek(System.out::println).forEach(System.out::println);
得到最大最小以及去重之后的结果
System.out.println(stream.mapToInt(String::length).max());
System.out.println(stream.mapToInt(String::length).min());
System.out.println(stream.mapToInt(String::length).distinct());
System.out.println(stream.allMatch("hello"::equals));
System.out.println(stream.anyMatch("hello"::equals));
System.out.println(stream.noneMatch("hello"::equals));
reduce类似于一个聚合函数,对一个组内的数据进行处理
字符串连接
System.out.println(stream.reduce("", String::concat));
获取最小值
stream.map(String::length).reduce(Integer.MAX_VALUE, Integer::min);
求和
stream.map(String::length).reduce(Integer::sum);
stream.map(String::length).reduce(1,Integer::sum);
类似于reduce,可以传入第一个参数为种子值,也可以说是初始值,然后第二个参数传入迭代值
Stream.iterate(3, n -> n-2).limit(10).forEach(System.out::println);
类似于一个底层的类,可以自定义流计算方法
class ownSupplier implements Supplier<String>{
Random random = new Random();
@Override
public String get() {
return random.nextInt(10) + ": random";
}
Stream.generate(new ownSupplier()).limit(5).forEach(System.out::println);
groupingBy:分组排序
Map<String, List<String>> group = Stream.generate(new ownSupplier()).limit(5)
.collect(Collectors.groupingBy(str -> str.split(":")[0]));
partitioningBy:分区排序
Map<Boolean, List<String>> partition = Stream.generate(new ownSupplier()).limit(5)
.collect(Collectors.groupingBy(str -> str.length() > 4));
summaryStatistics方法给出了流的基本信息,比如最大值、最小值、汇总值等,类似于sql中的max、min、xount等
Stream<Integer> istream = Stream.of(1, 2, 3, 4, 5, 6);
IntSummaryStatistics sumStream = istream.mapToInt(n -> n).summaryStatistics();
sumStream.getMax();
sumStream.getMin();
sumStream.getSum();
sumStream.getAverage();
sumStream.getCount();