引言
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
转自:https://blog.csdn.net/y_k_y/article/details/84633001
特点:
1 . 不是数据结构,不会保存数据。
2. 不会修改原来的数据源,它会将操作后的数据保存到另外一个对象中。(保留意见:毕竟peek方法可以修改流中元素)
3. 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算。
// 获取顺序流 Stream stream = new ArrayList().stream(); // 获取并行流 Stream parallelStream = new ArrayList().parallelStream(); // 数组转成流 Integer[] nums = {1,2,3}; Stream<Integer> streamArray = Arrays.stream(nums);
赋值
// of方法直接赋值 Stream<Integer> stream1 = Stream.of(1,2,3,4,5); stream1.forEach(System.out::println); // 1 2 3 4 5 // iterate生成生成无限顺序有序流,主要作用是抽象迭代逻辑 Stream<Integer> stream2 = Stream.iterate(2, x -> x * 2).limit(5); stream2.forEach(System.out::println); // 2 4 8 16 32 // generate生成无限顺序无序流,其中每个元素由提供的供应商生成。这适用于生成恒定流,随机元素流等。 Stream<Integer> stream3 = Stream.generate(new Random()::nextInt).limit(2); stream3.forEach(System.out::println); //15356208 -2042159
筛选与切片
filter:过滤流中的某些元素 limit(n):获取n个元素 skip(n):跳过n元素 distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素
Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10}; Stream<Integer> streamArray = Arrays.stream(nums); Stream<Integer> result = streamArray .distinct() // 去重 1 2 3 4 5 6 7 8 9 10 .filter(i -> (i > 2)) // 筛选出值>2的元素 3 4 5 6 7 8 9 10 .skip(2) // 跳过前2个元素 5 6 7 8 9 10 .limit(4); // 获取前4个元素 5 6 7 8
映射
map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10}; Stream<Integer> streamArray = Arrays.stream(nums); List<String> strings = streamArray .map(String::valueOf) // 通过String.valueOf()方法将各个元素转为字符串 .collect(Collectors.toList()); // 将流转为List集合
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
Stream<String> streamArray2 = Stream.of("1.2.3", "4.5.6", "7.8.9"); List<String> result = streamArray2 .flatMap(s -> Arrays.stream(s.split("\."))) //将流中的每个值都换成另一个流,然后分割 .collect(Collectors.toList()); // 1 2 3 4 5 6 7 8 9
排序
sorted():自然排序,流中元素需实现Comparable接口
List<String> list = Arrays.asList("a", "d", "c", "b", "x"); List<String> result = list.stream() .sorted() .collect(Collectors.toList()); // a b c d x
sorted(Comparator com):定制排序,自定义Comparator排序器
Person s1 = new Person("aa", 10); Person s2 = new Person("bb", 20); Person s3 = new Person("aa", 30); Person s4 = new Person("dd", 40); List<Person> personList = Arrays.asList(s1, s2, s3, s4);
//自定义排序:先按姓名升序,姓名相同则按年龄升序
personList.stream().sorted(
(o1, o2) -> {
if (o1.getName().equals(o2.getName())) {
return o1.getAge() - o2.getAge();
} else {
return o1.getName().compareTo(o2.getName());
}
}
).forEach(person -> System.out.println(person.getName()));
消费
peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值
Person s1 = new Person("aa", 10); Person s2 = new Person("bb", 20); Person s3 = new Person("aa", 30); Person s4 = new Person("dd", 40); List<Person> personList = Arrays.asList(s1, s2, s3, s4); personList.stream() .peek(person -> person.setAge(100)) .forEach(person -> System.out.println(person.getName()+":"+person.getAge()));
匹配
allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5); // 里面的元素是否都满足>10这个条件 boolean result = integers.stream().allMatch(i -> i > 10); // false
noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); // 里面的元素是否都 不 满足>10这个条件 boolean result = list.stream().noneMatch(i -> i > 10); // true
anyMatch:接收一个 Predicate 函数,只要流中存在元素满足该断言则返回true,否则返回false
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11); // 里面的元素是否存在满足>10这个条件 boolean result = list.stream().anyMatch(i -> i > 10); // true
findFirst:返回流中第一个元素
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11); // Optional对象常用于解决空指针问题 Optional<Integer> optional = list.stream().findFirst(); System.out.println(optional.get()); // 1
count:返回流中元素的总个数
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11); Long result = list.stream().count(); System.out.println(result); // 6
max:返回流中元素最大值
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11); Integer max = list.stream().max(Integer::compareTo).get(); // 11
min:返回流中元素最小值
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11); Integer min = list.stream().min(Integer::compareTo).get(); // 1
reduce
Optional<T> reduce(BinaryOperator<T> accumulator)
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6); Optional<Integer> optional = list.stream().reduce((x1, x2) -> x1 + x2); System.out.println(optional.get()); // 21(为流中元素的和) // 等效于 // Optional<Integer> optional = list.stream().reduce(Integer::sum);
T reduce(T identity, BinaryOperator<T> accumulator)
identity:返回实例 accumulator:累加器
String[] strings = {"a", "b", "c", "d", "e"}; String reduce2 = Arrays.stream(strings).reduce("", (a, b) -> { if (!"".equals(a)) { return a + "|" + b; } else { return b; } }); /** * 执行流程: * 第一个元素identity的值为"",因此a的初始值为"",b的初始值为流中第一个元素"a" * 第一次执行之后得到结果"a",然后执行结果的值赋给a,流中第二个元素的值"b"赋给b * 第二次执行之后得到结果"a|b",然后以此类推 */ System.out.println(reduce2); // a|b|c|d|e
reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner)
identity:返回实例 accumulator:累加器 combiner:组合器
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24); Integer v2 = list.stream().reduce(0, (x1, x2) -> { System.out.println("stream accumulator: x1:" + x1 + " x2:" + x2); return x1 - x2; }, // 第三个参数---参数的数据类型必须为返回数据类型,改参数主要用于合并多个线程的result值 //(Stream是支持并发操作的,为了避免竞争,对于reduce线程都会有独立的result) (x1, x2) -> { System.out.println("stream combiner: x1:" + x1 + " x2:" + x2); return x1 * x2; }); System.out.println(v2); // -300