Stream 是一组用来处理数组、集合的API,Stream API 提供了一种高效且易于使用的处理数据的方式。
Java 8 中之所以费这么大的功夫引入 函数式编程 ,原因有两个:
代码简洁函数式编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环。
多核友好,Java函数式编程使得编写并行程序从未如此简单,你需要的全部就是用用一下parallel()方法
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作
二、Stream特性
1、不是数据结构,没有内部存储,不会保存数据,故每个Stream流只能使用一次
2、不支持索引访问
3、支持并行
4、很容易生成数据或集合(List,Set)
5、支持过滤、查找、转换、汇总、聚合等操作
6、延迟计算,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算
三、分类
关于应用在Stream流上的操作,可以分成两种:
Intermediate(中间操作): 中间操作的返回结果都是Stream,故可以多个中间操作叠加;
Terminal(终止操作): 终止操作用于返回我们最终需要的数据,只能有一个终止操作。
使用Stream流,可以清楚地知道我们要对一个数据集做何种操作,可读性强。而且可以很轻松地获取并行化Stream流,不用自己编写多线程代码,可以让我们更加专注于业务逻辑。
无状态: 指元素的处理不受之前元素的影响;
有状态: 指该操作只有拿到所有元素之后才能继续下去。
非短路操作: 指必须处理所有元素才能得到最终结果;
短路操作: 指遇到某些符合条件的元素就可以得到最终结果,如 A || B,只要A为true,则无需判断B的结果。
四、Stream的创建
1、通过数组来生成
2、通过集合来生成
3、通过Stream.generate方法来创建
4、通过Stream.iterate方法来创建
5、其他Api创建
4.1 通过数组来生成
//通过数组来生成
static void gen1(){
String[] strs = {"a","b","c","d"};
Stream<String> strs1 = Stream.of(strs);//使用Stream中的静态方法:of()
strs1.forEach(System.out::println);//打印输出(a、b、c、d)
}
4.2 通过集合来生成
//通过集合来生成
static void gen2(){
List<String> list = Arrays.asList("1","2","3","4");
Stream<String>
stream = list.stream();//获取一个顺序流
stream.forEach(System.out::println);//打印输出(1,2,3,4)
}
4.3 通过Stream.generate方法来创建
//generate
static void gen3(){
Stream<Integer> generate = Stream.generate(() -> 1);//使用Stream中的静态方法:generate()
//limit 返回由该流的元素组成的流,截断长度不能超过maxSize
generate.limit(10).forEach(System.out::println);//打印输出(打印10个1)
}
4.4 通过Stream.iterate方法来创建
//使用iterator
static void gen4() {
Stream<Integer> iterate = Stream.iterate(1, x -> x + 1);//使用Stream中的静态方法:iterate()
iterate.limit(10).forEach(System.out::println);//打印输出(1,2,3,4,5,6,7,8,9,10)
}
4.4 其他Api创建
//其他方式
static void gen5(){
String str = "abcdefg";
IntStream stream =str.chars();//获取str 字节码
stream.forEach(System.out::println);//打印输出(97,98,99,100,101,102,103)
}
五、Stream的常用API
5.1 中间操作
1. filter: 过滤流中的某些元素
//中间操作:如果调用方法之后返回的结果是Stream对象就意味着是一个中间操作
Arrays.asList(1,2,3,4,5).stream()//获取顺序流
.filter((x)->x%2==0) // 2 4
.forEach(System.out::println);
//求出结果集中所有偶数的和
int count = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream()//获取顺序流
.filter(x -> x % 2 == 0).// 2 4 6 8
mapToInt(x->x).sum();//求和
System.out.println(count); //打印输出 20
2. distinct: 通过流中元素的 hashCode() 和 equals() 去除重复元素
Arrays.asList(1,2,3,3,3,4,5,2).stream()//获取顺序流
.distinct()//去重
.forEach(System.out::println);// 打印输出(1,2,3,4,5)
System.out.println("去重:---------------");
Arrays.asList(1,2,3,3,3,4,5,2).stream()//获取顺序流
.collect(Collectors.toSet())//Set()去重
.forEach(System.out::println);// 打印输出(1,2,3,4,5)
3. 排序
sorted():返回由此流的元素组成的流,根据自然顺序排序。
sorted(Comparator com):返回由该流的元素组成的流,根据提供的 Comparator进行排序。
//获取最大值和最小值但是不使用min和max方法
List<Integer> list = Arrays.asList(1,2, 3,4, 5, 6);
Optional<Integer> min = list.stream().sorted().findFirst();//自然排序 根据数字从小到大排列
System.out.println(min.get());//打印输出(1)
Optional<Integer> max2 = list.stream().sorted((a, b) -> b - a).findFirst();//定时排序 根据最大数进行排序
System.out.println(max2.get());//打印输出(6)
//按照大小(a-z)排序
Arrays.asList("java","c#","python","scala").stream().sorted().forEach(System.out::println);
//按照长度排序
Arrays.asList("java","c#","python","scala").stream().sorted((a,b)->a.length()-b.length()).forEach(System.out::println);
4. 截取