一、什么是 Stream?
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。
使用 Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
二、Stream 的特点
- stream 自己不会保存数据。
- 不会改变数据源,相反,他们会返回一个持有结构的新的 Stream。
- Stream 操作是延迟执行的,因此,它会等到需要结果时才执行。
三、Stream 的三个操作步骤
产生 Stream
① 通过 Collections 系列集合提供的 stream()方法或 parallelStream()获取
② 通过 Arrays 中的静态方法获取
③ 通过 Stream 类中的静态方法 of()获取
④ 创建无限流
⑤ ...中间操作
(1)筛选与切片:
① Stream<T> filter(Predicate predicate); // 过滤(返回值 boolean)
② Stream<T> limit(long maxSize); // 限制
③ Stream<T> skip(long n); // 跳过
④ Stream<T> distinct(); // 去重(比较 hash 值)
(2)映射
① Stream<R> map(Function mapper); // 参数 lambda 表达式(有返回值)
② Stream<R> flatMap(Function mapper); // 参数 lambda 表达式(有返回值)
(3)排序
① Stream<T> sorted() // 自然排序 Comparable
② Stream<T> sorted(Comparator comparator); // 定制排序
(4)消费(与 map() 相似)
① Stream<T> peek(Consumer action); // 参数 lambda 表达式(无返回值)终止操作(终端操作)
(1)查找与匹配
allMatch:检查是否匹配所有元素
noneMatch:检查是否没匹配所有元素
anyMatch:检查是否至少有一个元素匹配
findFirst:返回流中第一个元素
findAny:返回流中的任意元素
count:返回流中元素的总个数
max:返回流中元素最大值
min:返回流中元素最小值
(2)归约与收集
① Optional<T> reduce(BinaryOperator<T> accumulator)
② R collect(Collector collector);
四、Stream 演示
以下为全部代码,可直接运行
Person.java
package com.wl.model;
/**
* @author WL
* @date : 2021年6月3日 08:27:19
*/
public class Person implements Comparable<Person> {
private String name;
private Integer age;
private String gender;
public Person() {
}
public Person(String name, Integer age, String gender) {
super();
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", gender=" + gender + "]";
}
@Override
public int compareTo(Person person) {
return person.getAge() - this.age;
}
}
StreamDemo.java
package com.wl.stream;
import com.wl.model.Person;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author WL
* @date : 2021年6月3日 08:27:19
*/
public class StreamDemo {
public static Person person1 = new Person("Tom", 20, "男");
public static Person person2 = new Person("Scott", 21, "女");
public static Person person3 = new Person("John", 22, "男");
public static Person person4 = new Person("Bob", 23, "女");
public static List<Person> list = Arrays.asList(person1, person2, person3, person4, person4);
public static void main(String[] args) {
System.out.println("请输入要要演示的方法序号:");
System.out.println("1.创建 Stream");
System.out.println("2.中间操作--筛选与切片");
System.out.println("3.中间操作--映射");
System.out.println("4.中间操作--映射");
System.out.println("5.中间操作--排序");
System.out.println("6.查找与匹配");
System.out.println("7.归约与收集");
System.out.println("8.退出");
System.out.println("请输入数字:(例:6)");
while (true) {
int num = new Scanner(System.in).nextInt();
if (num == 1) {
test1();
} else if (num == 2) {
test2();
} else if (num == 3) {
test3();
} else if (num == 4) {
test4();
} else if (num == 5) {
test5();
} else if (num == 6) {
test6();
} else if (num == 7) {
test7();
} else if (num == 8) {
break;
} else {
System.err.println("您输入的数字不正确,请重新输入:");
}
}
}
/**
* 创建 Stream
*/
public static void test1() {
// 1. 通过 Collections 系列集合提供的 stream()方法或 parallelStream()获取
List<String> list = Arrays.asList("aaa", "bbb", "ccc");
list.forEach(System.out::println);
// 2. 通过 Arrays 中的静态方法获取
String[] strArr = {"aaa", "bbb", "ccc"};
Stream<String> stream2 = Arrays.stream(strArr);
// 3. 通过 Stream 类中的静态方法 of()获取
Stream<String> stream3 = Stream.of("111", "222", "333");
// 4. 创建无限流
// 迭代
Stream<Integer> stream4 = Stream.iterate(0, x -> x + 2);
stream4.limit(20).forEach(System.out::println);
// 生成
Stream.generate(Math::random).limit(8).forEach(System.out::println);
}
/**
* 中间操作--筛选与切片
*/
public static void test2() {
// distinct()比较 hash 值
Stream<Person> stream = list.stream().filter(person -> person.getAge() > 20).distinct();
// 终止,无终止,中间操作不执行
stream.forEach(System.out::println);
}
/**
* 中间操作--映射
*/
public static void test3() {
System.out.println("---------------------map----------------------------");
Stream<Person> stream1 = list.stream().map(person -> {
person.setAge(person.getAge() + 10);
return person;
});
stream1.forEach(System.out::println);
System.out.println("----------------------map----------------------------");
Stream<String> strs = list.stream().map(Person::getName);
strs.forEach(System.out::println);
System.out.println("----------------------flatMap----------------------------");
List<String> strList = Arrays.asList("a,b,c", "d,e", "f,g,h,i");
// 把 {{a,b,c},{d,e},{f,g,h,i}} 流转化为 {a,b,c,d,e,f,g,h,i}
Stream<String> stream2 = strList.stream().flatMap(s -> {
String[] strArr = s.split(",");
return Arrays.stream(strArr);
});
stream2.forEach(System.out::println);
}
/**
* 中间操作--排序
*/
public static void test4() {
System.out.println("----------------------sorted Comparable----------------------------");
// 使用 sorted(),Person 类需实现 Comparable 接口,重写 compareTo()方法
/*
* @Override
* public int compareTo(Person person) {
* return person.getAge() - this.age;
* }
*/
list.stream().sorted().forEach(System.out::println);
System.out.println("----------------------sorted Comparator----------------------------");
System.out.println("----------------------age从大到小----------------------------");
list.stream().sorted((p1, p2) -> p2.getAge() - p1.getAge()).forEach(System.out::println);
System.out.println("----------------------age从小到大----------------------------");
list.stream().sorted(Comparator.comparingInt(Person::getAge)).forEach(System.out::println);
}
/**
* 中间操作--排序
*/
public static void test5() {
list.stream().peek(p -> p.setAge(25)).forEach(System.out::println);
}
/**
* 查找与匹配
*/
public static void test6() {
System.out.println(list.stream().allMatch(x -> x.getGender().equals("男")));
System.out.println(list.stream().noneMatch(x -> x.getGender().equals("男")));
System.out.println(list.stream().anyMatch(x -> x.getGender().equals("男")));
System.out.println(list.stream().findFirst().get());
System.out.println(list.stream().findAny().get());
System.out.println(list.stream().count());
System.out.println(list.stream().max(Comparator.comparingInt(Person::getAge)).get());
System.out.println(list.stream().min(Comparator.comparingInt(Person::getAge)).get());
}
/**
* 归约与收集
*/
public static void test7() {
Integer ageSum = list.stream().map(Person::getAge).reduce(Integer::sum).get();
System.out.println("年龄总和:" + ageSum);
Set<String> nameSet = list.stream().map(Person::getName).collect(Collectors.toSet());
System.out.println(nameSet);
HashSet<String> nameHashSet = list.stream().map(Person::getName).collect(Collectors.toCollection(HashSet::new));
System.out.println(nameHashSet);
Double avgAge = list.stream().collect(Collectors.averagingDouble(Person::getAge));
System.out.println("平均年龄:" + avgAge);
Integer a = list.stream().mapToInt(Person::getAge).sum();
System.err.println(a);
}
}