Stream的操作中有中间操作和终端操作,顾名思义,中间操作就是对stream流的一些操作,操作对象时stream本身,终端操作既是对流的处理结果,为了直观的了解,我们看下接口定义:
public interface Stream<T> extends BaseStream<T, Stream<T>> {Stream<T> filter(Predicate<? super T> predicate);<R> Stream<R> map(Function<? super T, ? extends R> mapper);IntStream mapToInt(ToIntFunction<? super T> mapper);LongStream mapToLong(ToLongFunction<? super T> mapper);DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);Stream<T> distinct();Stream<T> sorted();Stream<T> sorted(Comparator<? super T> comparator);Stream<T> peek(Consumer<? super T> action);Stream<T> limit(long maxSize);Stream<T> skip(long n);void forEach(Consumer<? super T> action);void forEachOrdered(Consumer<? super T> action);Object[] toArray();<A> A[] toArray(IntFunction<A[]> generator);T reduce(T identity, BinaryOperator<T> accumulator);Optional<T> reduce(BinaryOperator<T> accumulator);<U> U reduce(U identity,BiFunction<U, ? super T, U>accumulator,
BinaryOperator<U> combiner);<R> R collect(Supplier<R> supplier,iConsumer<R, ? super T> accumulator,iConsumer<R, R> combiner);<R, A> R collect(Collector<? super T, A, R> collector);Optional<T> min(Comparator<? super T> comparator);Optional<T> max(Comparator<? super T> comparator);long count();boolean anyMatch(Predicate<? super T> predicate);boolean allMatch(Predicate<? super T> predicate);boolean noneMatch(Predicate<? super T> predicate);Optional<T> findFirst();Optional<T> findAny();public static<T> Builder<T> builder() {return new Streams.StreamBuilderImpl<>();}public static<T> Stream<T> empty() {return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false);}public static<T> Stream<T> of(T t) {return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);}public static<T> Stream<T> of(T... values) {return Arrays.stream(values);}
}
对于返回值为** 接口本身的Stream ** 或者返回 其他对象类型的&#xff0c;返回接口类型的我们都可认为是中间操作&#xff0c;返回 其他具体类型的为终端操作。
下面我们来具体看每个方法&#xff1a;
1、filter(Predicate) 将结果为false的元素过滤掉
&#64;Test
public void testFilter(){Stream<Integer> stream &#61; Stream.of(1, 2, 3);stream.filter(e->e > 2).forEach(System.out::println);
}
filter() 传入需要过滤的条件
2、map(fun) 转换元素的值&#xff0c;可以用方法引元或者lambda表达式
&#64;Test
public void testMap(){Stream<Integer> stream &#61; Stream.of(1, 2, 3);stream.map(o -> Integer.toString(o)).forEach(s->{System.out.println(s);System.out.println(s.getClass());});List<Dish> dishes &#61; Arrays.asList(new Dish("beef", "100", 200, Dish.Type.MEAT),new Dish("pork", "false", 800, Dish.Type.MEAT),new Dish("rice", "true", 350, Dish.Type.OTHER));dishes.stream().map(Dish::getName).forEach(System.out::println);
}
可以看到&#xff0c;使用map方法实现了Integer-> String的类型转换&#xff0c;也可以获取对象的某一属性值等等。
3、flatMap(fun) 若元素是流&#xff0c;将流摊平为正常元素&#xff0c;再进行元素转换
String [] arr &#61; {"aaa","bbb","ccc"};
Arrays.stream(arr).map(s-> s.split("")).forEach(System.out::println);
List<String[]> collect &#61; Arrays.stream(arr).map(s -> s.split("")).collect(Collectors.toList());
我们可以看到使用map时输出的是一个地址&#xff0c;返回的类型实际是 List 使用flatMap时
List<String> list &#61; Arrays.stream(arr).map(s -> s.split("")).flatMap(Arrays::stream).collect(Collectors.toList());
Arrays.stream(arr).map(s->s.split("")).flatMap(Arrays::stream).forEach(System.out::println);
可以看到返回的类型为List &#xff0c;将整个外层list包含的所有元素放到一个层面处理。
4、limit(n) 保留前n个元素
List<Dish> mean &#61; Arrays.asList(new Dish("pork", "false", 800, Dish.Type.MEAT),new Dish("beef", "false", 700, Dish.Type.MEAT),new Dish("chicken", "false", 400, Dish.Type.MEAT),new Dish("french fries", "true", 530, Dish.Type.OTHER),new Dish("rice", "true", 350, Dish.Type.OTHER),new Dish("season fruit", "true", 120, Dish.Type.OTHER),new Dish("pizza", "true", 550, Dish.Type.OTHER),new Dish("prawns", "false", 300, Dish.Type.FISH),new Dish("salmon", "false", 450, Dish.Type.FISH)
);
List<Dish> dishes &#61; mean.stream().limit(2).collect(Collectors.toList());
System.out.println(dishes.size());
mean.stream().limit(2).forEach(System.out::println);
5、skip(n) 跳过前n个元素
mean.stream().skip(7).forEach(System.out::println);
对于limit 和 skip 配合使用可以实现分页操作
**6、distinct() 去重 剔除重复元素 **
&#64;Test
public void testDistinct(){int[] arr &#61; {1,1,2,2,3,4,5};Arrays.stream(arr).distinct().forEach(System.out::println);
}
7、sorted() 排序 默认升序
int[] arr &#61; {5,7,3,1,8,4};
Arrays.stream(arr).sorted().forEach(System.out::println);
8、sorted(Comparator) 按传入的条件排序
List<Dish> mean &#61; Arrays.asList(new Dish("pork", "false", 800, Dish.Type.MEAT),new Dish("beef", "false", 700, Dish.Type.MEAT),new Dish("chicken", "false", 400, Dish.Type.MEAT),new Dish("french fries", "true", 530, Dish.Type.OTHER),new Dish("rice", "true", 350, Dish.Type.OTHER),new Dish("season fruit", "true", 120, Dish.Type.OTHER),new Dish("pizza", "true", 550, Dish.Type.OTHER),new Dish("prawns", "false", 300, Dish.Type.FISH),new Dish("salmon", "false", 450, Dish.Type.FISH)
);
mean.stream().sorted(Comparator.comparing(Dish::getCalories)).map(Dish::getCalories).forEach(System.out::println);
mean.stream().sorted(Comparator.comparing(Dish::getCalories).reversed()).map(Dish::getCalories).forEach(System.out::println);
9、peek(fun) 流不变 接收一个没有返回值的λ表达式&#xff0c;可以做一些输出&#xff0c;外部处理
&#64;Test
public void testPeek(){int [] arr &#61; {1,1,2,3,4,4,5};Arrays.stream(arr).distinct().map(o-> o*2).peek(s->System.out.println("peek 做一些输出操作"&#43;s)).forEach(System.out::println);
}
peek 和 map 的区别
peek 的定义
Stream<T> peek(Consumer<? super T> action);
熟悉lambda的都知道Consumer的实现类 应该只有一个方法&#xff0c;该方法返回类型为void。
Consumer<Integer> c &#61; i -> System.out.println("hello" &#43; i);
map的定义
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
我们发现Function 比 Consumer 多了一个 return。 map接收一个有返回值的lambda表达式&#xff0c;之后Stream的泛型类型将转换为map参数λ表达式返回的类型
Function<Integer,String> f &#61; x -> {return "hello" &#43; i;};