对大数据有了解的同学都知道,大数据的核心就是数据计算,Stream API正是对数据的计算处理。Stream API是Java8推出的新特性之一,它是强大的数据流处理工具,能够非常简洁方便的处理集合数组等数据。让我们来认识一下它吧!
Stream翻译过来是流,可以将其处理流程比喻成水净化处理,水流处理首先要有水源,其次要对水流进行处理,比如过滤水的过滤器,最后要把处理过的水收集起来供人们使用。同理Stream API也是如此,要有数据源(水源),过程处理(过滤器),处理结果收集(水收集)。因此Stream API重要的三个部分已经浮出水面:
一、数据源,获取流
拿到数据源,获取一个stream流,常见的数据源就是集合数组;
1.通过集合Collection获取stream流,从Java1.8开始Collection扩展了一对方法;
/**
* 该方法是Java1.8开始
* java.util.Collection扩展的方法,
* 返回的是顺序流
*/default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
/**
* 该方法是Java1.8开始Collection拓展方法,
* 返回并行流
*/default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
// 使用stream方法获取流
List<String> nums = Arrays.asList("1", "2", "3");
// 获取顺序流
String newStr = nums.stream()
// 过滤出来不包含*的字符串
.filter(s ->!s.contains("*"))
// 再用%将上一步筛选出来的字符串用%连接起来成一个新字符串
.collect(Collectors.joining("%"));
// 打印结果 newStr = 1%2%3
System.out.println("newStr = " + newStr);
// 返回一个并行流
Stream<String> stringStream = nums.parallelStream();
2.通过数组获取流; Arrays类的stream方法, 从Java1.8开始;
/**
* 该方法是Java1.8开始
* java.util.Arrays类的stream方法,
* 由某类型的数组获取流(顺序流)
*/public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
// 由某类型的数组获取流(顺序流)
Stream stream = Arrays.stream(
new User[]{new User("1"),
new User("2"),
new User("3")});
3. Stream类的of方法( 底层还是调用Arrays.stream()方法 );
/**
* 该方法是Java1.8开始
* java.util.stream.Stream类的of方法,
* 由某类型的数组获取流(顺序流)
*/public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
// 由某类型的对象排列获取流(顺序流)
Stream stream =Stream.of(new User("1"),
new User("2"),
new User("3"));
4.创造无限流,使用java.util.stream.Stream的iterate方法或generate方法
/**
* java.util.stream.Stream的iterate方法
* @param seed 传入的种子
* @param f 生成新的项执行的算法
*/public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
// 方法体略多,省略方法体
}
/**
* java.util.stream.Stream的generate方法
* @param s 生成新的项执行的算法
*/public static<T> Stream<T> generate(Supplier<T> s) {
Objects.requireNonNull(s);
return StreamSupport.stream(
new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}
// 种子是1,每次乘2生成新的项
Stream<Integer> stream = Stream.iterate(1, x -> x * 2);
// 收集5项并打印 //打印结果 1 2 4 8 16
stream.limit(5).forEach(System.out::println);
// 生成随机数
Stream<Double> stream1 = Stream.generate(Math::random);
// 收集5项并打印
stream1.limit(5).forEach(System.out::println);
二、数据过程处理(过程操作)
中间操作,对数据流进行操作处理,常见的有过滤、计数等操作;下面用代码介绍一些基本的中间操作;
List<Integer> nums = Arrays.asList(1, 2, 3, 3, 4, 5);
// 获取stream流
nums.stream()
// 筛选大于1的元素
.filter(s -> s > 1)
// 遍历打印 结果是2 3 3 4 5
.forEach(System.out::println);
nums.stream()
// 去重
.distinct()
// 遍历打印 结果是1 2 3 4 5
.forEach(System.out::println);
nums.stream()
// 截取出前3个元素作为结果
.limit(3)
// 遍历打印 结果是1 2 3
.forEach(System.out::println);
nums.stream()
// 跳过前3个元素,剩下的作为结果
.skip(3)
// 遍历打印 结果是3 4 5
.forEach(System.out::println);
nums.stream()
// 映射,每个元素映射成自己的平方
.map(s -> s * s)
// 遍历打印 结果是1 4 9 9 16 25
.forEach(System.out::println);
nums.stream()
// 按自然顺序排序
.sorted()
// 遍历打印 结果是1 2 3 3 4 5
.forEach(System.out::println);
三、结果收集(终止操作)
终止操作,对步骤二的处理结果进行收集,常见的终止操作有遍历(步骤二中的代码中forEach就是遍历操作),收集等方式,以便后续进行其他处理;下面用代码介绍一些基本的终止操作;
/**
* 终止操作之count
*/List<Integer> nums = Arrays.asList(1, 2, 3, 3, 4, 5);
// 获取stream流
long count = nums.stream()
// 筛选大于1的元素
.filter(s -> s > 1)
// 计数,流中元素共有几个
.count();
// 输出count = 5
System.out.println("count = " + count);
/**
* 终止操作之collect
*/// 获取stream流
List<Integer> collect = nums.stream()
// 筛选大于1的元素
.filter(s -> s > 1)
// 收集流中所有的元素到一个List
.collect(Collectors.toList());
// 输出collect = [2, 3, 3, 4, 5]
System.out.println("collect = " + collect);
当然终止操作不止上面的forEach,collect,count,还有一些其他的如max,min之类的,大家感兴趣的可以去了解下,就不在一一列举了。
注意:
- Stream流式编程并不能避免空指针,需要自行判断。可以用Optional配合使用。
- 流进行了终止操作后,不能再次使用。
- 并行流和顺序流的区别是并行流相当于多线程并行处理,因此并行流遍历有序集合时,会出现乱序。
希望大家点赞评论转发[送心]。橙子这里祝大家金钱爆富[大笑]