文章目录
- 一、简介
- 二、操作分类
- 创建流
- 通过集合
- 通过数组
- 通过Stream的of()方法
- 中间操作
- 无状态
- 有状态
- 结束操作
- 非短路操作
- 短路操作
一、简介
JDK 8 引入了 Stream API,它是用于处理集合数据的功能强大的库。Stream API 提供了一种更为简洁、灵活和函数式的方式来进行集合的操作和处理。
Stream API 有三大特性:
- 不存储数据:Stream API 并不会在内存中存储数据,它仅仅是对源数据进行操作和处理的管道,当我们对一个集合或数组创建流时,流只是作为一种处理方式存在,并没有实际保存数据。
- 不改变源数据:Stream API 的操作不会改变原始数据源中的元素,所有的中间操作(如过滤、映射、排序)都会产生一个新的流,而不是直接修改原始数据。这种特性确保了数据的不可变性。
- 延时执行:Stream API 使用了延迟执行的概念。它并不会立即执行流的操作,而是等到需要结果时才进行计算。这样可以避免不必要的计算,提高效率并节省资源。只有在终端操作(如聚合、收集、计数)被调用时,流才会进行实际的计算。
二、操作分类
在使用 Stream API 进行集合操作时,一般会遵循以下步骤:
- 创建流:通过集合或数组创建一个流
- 中间操作:对流进行一系列的中间操作,例如过滤、映射、排序等。这些操作可以按照需求进行链式调用
- 结束操作:中间操作只是一种标记,只有结束操作才会触发实际计算
其中中间操作又分为,无状态和有状态,结束操作又分为短路操作和非短路操作
创建流
通过集合
可以使用 Collection
接口中的 stream()
方法或者 parallelStream()
方法来创建一个流
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
通过数组
可以使用 Arrays
类中的静态方法 stream()
来创建一个数组的流
String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
通过Stream的of()方法
可以使用 Stream
类中的静态方法 of()
来根据指定的元素创建一个流
Stream<String> stream = Stream.of("a", "b", "c");
中间操作
无状态
元素的处理不受前一个元素影响
- filter(过滤):接收一个
Predicate
参数,根据Predicate
的判断结果决定是否保留流中的元素,true
留下,false
丢弃 - map、mapToInt、mapToLong、mapToDouble(转换):map 方法接收一个
Function
参数,将流中的每个元素通过该函数进行转换,mapToInt、mapToLong、mapToDouble 和 map 差不多,只是强制指定了返回值必须是 int、long、double 类型 - flatMap、flatMapToInt、flatMapToLong、flatMapToDouble(合并):将一个或多个流合并成一个新流,flatMapToInt、flatMapToLong、flatMapToDouble 和 f latMap 差不多,只是返回的是对应的 IntStream、LongStream、DoubleStream 流
- peek(监测):接受一个
Consumer
函数作为参数,该函数会在流的每个元素被处理时被调用。它可以用于在处理流的过程中观察每个元素的值,而不会改变流的内容
//filter
public static void main(String[] args) {String[] str = {"a", "b", "c"};Stream.of(str).filter(t -> t.equals("a")).forEach(System.out::println);//输出//a
}//map、mapToInt、mapToLong、mapToDouble
public static void main(String[] args) {String[] str = {"a", "b", "c"};Stream.of(str).map(t -> t.toUpperCase()).forEach(System.out::println);Stream.of(str).mapToInt(t -> t.hashCode()).forEach(System.out::println);//输出//A//B//C//97//98//99
}//flatMap、flatMapToInt、flatMapToLong、flatMapToDouble
public static void main(String[] args) {List<String> a = new ArrayList<>();a.add("a");a.add("b");List<String> b = new ArrayList<>();b.add("c");b.add("d");Stream.of(a, b).flatMap(u -> u.stream()).forEach(System.out::println);//输出//a//b//c//d
}//peek
public static void main(String[] args) {String[] str = {"a", "b", "c"};Stream.of(str).peek(t -> System.out.println("this is " + t)).collect(Collectors.toList());//输出//this is a//this is b//this is c
}
有状态
必须等所有元素处理完毕之后才知道最终的结果
- distinct(去重):去除重复的元素
- sorted(排序):不传参数,会按照自然排序,也可以传一个比较器参数,会根据比较器定义的顺序排序
- limit(限制):截取前n个元素
- skip(跳过):跳过n个元素,返回之后的元素
//distinct
public static void main(String[] args) {String[] str = {"a", "a", "b", "b", "c"};Stream.of(str).distinct().forEach(System.out::println);//输出//a//b//c
}//sorted
public static void main(String[] args) {String[] str = {"banana", "apple", "pineapple", "pear", "watermelon"};Stream.of(str).sorted().forEach(System.out::println);System.out.println("---------------");Stream.of(str).sorted(Comparator.comparing(String::length)).forEach(System.out::println);//输出//apple//banana//pear//pineapple//watermelon//---------------//pear//apple//banana//pineapple//watermelon
}//limit
public static void main(String[] args) {String[] str = {"a", "b", "c", "d", "e"};Stream.of(str).limit(2).forEach(System.out::println);//输出//a//b
}//skip
public static void main(String[] args) {String[] str = {"a", "b", "c", "d", "e"};Stream.of(str).skip(2).forEach(System.out::println);//输出//c//d//e
}
结束操作
非短路操作
需要处理完所有元素
- forEach(循环):循环操作Stream中数据
- forEachOrdered(排序循环):按照流的遭遇顺序来处理元素,在并行流中使用
- toArray(转数组):不传参数的话,返回的是对象数组,也可以接收一个 IntFunction<A[]> generator 参数来指定返回数据的类型
- reduce(聚合):聚合操作,一般用来做统计
- collect(收集):将元素收集到一个集合或其他数据结构里
- min(最小值):根据传入的比较器,找到最小的元素
- max(最大值):根据传入的比较器,找到最大的元素
- count(总数量):计数,统计元素数量
//forEach
public static void main(String[] args) {String[] str = {"a", "b", "c"};Stream.of(str).forEach(System.out::println);//输出//a//b//c
}//toArray
public static void main(String[] args) {String[] str = {"1", "2", "3"};Object[] objectArray = Stream.of(str).toArray();String[] strArray = Stream.of(str).toArray(String[]::new);
}//reduce
public static void main(String[] args) {Integer[] array = {1, 2, 3, 4, 5};Optional<Integer> optional = Stream.of(array).reduce((x, y) -> x + y);optional.ifPresent(System.out::println);//输出//15
}//collect
public static void main(String[] args) {Integer[] array = {1, 2, 3, 4, 5};List<Integer> list = Stream.of(array).collect(Collectors.toList());System.out.println(list);//输出//[1, 2, 3, 4, 5]
}//min
public static void main(String[] args) {Integer[] array = {1, 2, 3, 4, 5};Optional<Integer> min = Stream.of(array).min(Comparator.comparing(Integer::intValue));min.ifPresent(System.out::println);//输出//1
}//max
public static void main(String[] args) {Integer[] array = {1, 2, 3, 4, 5};Optional<Integer> max = Stream.of(array).max(Comparator.comparing(Integer::intValue));max.ifPresent(System.out::println);//输出//5
}//count
public static void main(String[] args) {String[] str = {"a", "b", "c"};long count = Stream.of(str).count();System.out.println(count);//输出//3
}
短路操作
一旦满足或不满足条件,就结束计算,不用处理完所有元素
- anyMatch:只要有一个符合条件就返回 true
- allMatch:所有都符合条件返回 true
- noneMatch:所有数据都不符合条件返回true
- findFirst:获取第一个元素
- findAny:获取任一元素,一般用于并行流
//anyMatch
public static void main(String[] args) {String[] str = {"banana", "apple", "pineapple", "pear", "watermelon"};boolean b = Stream.of(str).anyMatch(t -> t.length() == 4);boolean b2 = Stream.of(str).anyMatch(t -> t.length() == 3);System.out.println(b);System.out.println(b2);//输出//true//false
}//allMatch
public static void main(String[] args) {String[] str = {"banana", "apple", "pineapple", "pear", "watermelon"};boolean b = Stream.of(str).allMatch(t -> t.length() >= 4);boolean b2 = Stream.of(str).allMatch(t -> t.length() >= 5);System.out.println(b);System.out.println(b2);//输出//true//false
}//noneMatch
public static void main(String[] args) {String[] str = {"banana", "apple", "pineapple", "pear", "watermelon"};boolean b = Stream.of(str).noneMatch(t -> t.length() >= 4);boolean b2 = Stream.of(str).noneMatch(t -> t.length() <= 3);System.out.println(b);System.out.println(b2);//输出//false//true
}//findFirst
public static void main(String[] args) {String[] str = {"banana", "apple", "pineapple", "pear", "watermelon"};Optional<String> first = Stream.of(str).findFirst();first.ifPresent(System.out::println);//输出//banana
}//findAny
public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);numbers.parallelStream().filter(n -> n % 2 == 0).findAny().ifPresent(System.out::println);//输出//2 or 4
}