Stream是Java API的新成员,可以通过声明的方式来处理数据集合,其实就是遍历集合的高级迭代器。这篇博客会先引入stream的一个简单实例,然后举例说明stream的几种创建方式。
入门需求:有一些菜谱,现在需要选择出这些菜谱中热量低于指定的菜名,同时按照热量排序输出菜名。先上相关代码
Dish实例
package com.learn.stream.common;
/**
* autor:liman
* createtime:2019/8/14
* comment: 菜肴
*/
public class Dish {
private final String name;//姓名
private final boolean vegetarian;//是否是蔬菜
private final int calories;//热量
private final Type type;//类型
public Dish(String name, boolean vegetarian, int calories, Type type) {
this.name = name;
this.vegetarian = vegetarian;
this.calories = calories;
this.type = type;
}
//省略getter和setter方法
//类型
public enum Type{MEAT,FISH,OTHER}
}
如果没有Stream,之前的实现方式是这样的
/**
* 获取热量小于400的菜的名字
* @param dishes
* @return
*/
public static List getDishNameByCalories(List dishes){
List lowCaolories = new ArrayList();
for(Dish dish:dishes){
if(dish.getCalories()<400){
lowCaolories.add(dish);
}
}
Collections.sort(lowCaolories,(d1,d2)->Integer.compare(d1.getCalories(),d2.getCalories()));
List names = new ArrayList<>();
for(Dish dish:lowCaolories){
names.add(dish.getName());
}
return names;
}
可以看到为了实现这个需求,我们定义了很多没有太多意义的中间变量。如果有了stream就是如下的方式处理
/**
*
* @param dishes
* @return
*/
public static List getDishNameLowCaloriesByStream(List dishes){
return dishes.stream()//这里就是将集合变成stream
.filter(d->d.getCalories()<400)
.sorted(Comparator.comparing(Dish::getCalories))
.map(Dish::getName)
.collect(toList());//这里的filter,sorter,map,collect都是中间操作,这个后面会详谈
}
Collection中的源码,其中有stream和parallelStream,前者是创建stream后者是创建并行的stream。
public interface Collection extends Iterable {
default Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
意味着我们可以通过Collection的各种实现类直接创建Stream,简单实例如下所示
/**
* Collection接口及其子类都能利用stream()方法构建stream流。
*
* @return
*/
public static Stream createStreamFromCollection() {
List list = Arrays.asList("hello", "alex", "liman", "world", "stream");
return list.stream();
}
Stream.of可以直接创建Stream流,源码如下,其实底层也是用的Arrays.stream
@SafeVarargs
@SuppressWarnings("varargs") // Creating a stream from an array is safe
public static Stream of(T... values) {
return Arrays.stream(values);
}
实例如下:
/**
* 直接利用Stream的ofStream方法构建Stream
*
* @return
*/
public static Stream createStreamFromValues() {
return Stream.of("hello", "alex", "liman", "world", "stream");
}
在上述中已经发现Stream.of底层就是用的Arrays.stream完成流的构建
/**
* Arrays并没有继承至Collections但是也有自己的Stream方法
*
* @return
*/
public static Stream createStreamFromArrays() {
String[] strings = {"hello", "alex", "liman", "world", "stream"};
return Arrays.stream(strings);
}
Stream类中的generate方法源码如下:这个方法只需要接受一个Supplier接口。
public static Stream generate(Supplier s) {
Objects.requireNonNull(s);
return StreamSupport.stream(
new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}
Supplier接口之前有介绍,这里不再赘述
public static Stream createStreamFromGenerate(){
Stream stream = Stream.generate(Math::random);
return stream;
}
这个直接上实例。
public static Stream createStreamFromIterator() {
Stream iterate = Stream.iterate(0, n -> n+2);
return iterate;
}
其实Stream还是File进行操作,上述只是简单列举了一些创建Stream对象的方法,但是stream让人着迷的地方在于其各种中间处理方式,下篇博客会进行总结。