Stream流
Stream关注的是对数据的运算,与CPU打交道,
集合关注的是数据的存储,与内存打交道,
stream是数据渠道,用于操作数据源(集合,数组等)所生成的元素序列。”集合讲的是数据,Stream讲的是计算“
注意点:
- Stream自己不会存储元素
- Stream不会改变源对象,相反,他们会返回一个持有结果的新Stream
- Stream操作是延迟执行的,这意味着他们会等到需要结果的时候才执行
Stream的操作的三个步骤
1.创建Stream
一个数据源,获取一个流
2.中间操作
一个中间操作链,对数据源的数据进行处理
3.终止操作
一旦执行终止操作,就执行中间操作链,并产生结果,之后,不会再被使用
代码实例(创建Stream)
// 创建Stream方式一:通过集合
public void test1() {
List<Employee> list = EmployeeData.getEmployees();
// default Stream<E> stream() : 返回一个顺序流
Stream<Employee> stream = list.stream();
// default Stream<E> parallelStream() : 返回一个并行流
Stream<Employee> parallelStream = list.parallelStream();
}
// 创建Stream方式二:通过数组
public void test2() {
int[] arr = new int[]{1, 2, 3, 5, 4};
// 调用Arrays工具类的static Stream<T> stream(T[] array) 返回一个流
IntStream stream = Arrays.stream(arr);
Employee employee = new Employee(1001, "Tom");
Employee employee1 = new Employee(1002, "Jerry");
Employee[] employees = new Employee[] {employee, employee1};
Stream<Employee> employeeStream = Arrays.stream(employees);
}
// 创建Stream方式三: 通过static<T> Stream<T> of(T... values)
public void test3() {
// 返回包装类对象
int i1 = 1;
int i2 = 2;
Stream<Integer> stream = Stream.of(i1, i2);
Stream<Integer> integerStream = Stream.of(1, 2, 3, 5, 4);
}
// 创建Stream方式四: 创建无限流,可以用于造一些数据
public void test4() {
// 迭代
// 遍历前十个偶数
// static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
// 生成
// static<T> Stream<T> generate(Supplier<T> s)
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
代码实例(中间操作)
public void test1() {
List<Employee> list = EmployeeData.getEmployees();
// Stream<T> filter(Predicate<? super T> predicate) - 接收Lambda,从流中排除某些元素
list.stream().filter(e -> e.getSalary() >= 80000).forEach(System.out::println);
// skip(n) - 跳过元素,返回一个跳过了前n个元素的流,若流中元素不足n个,则返回一个空流
list.stream().skip(100).forEach(System.out::println);
System.out.println("=============");
// distinct() -筛选,通过流所生成元素的hashCode()和equals() 去除重复元素
list.stream().distinct().forEach(System.out::println);
}
public void test2() {
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
// <R> Stream<R> map(Function<? super T, ? extends R> mapper)
// map(Function f) - 接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上,并将其映射成一个新的元素
list.stream().map(String::toUpperCase).forEach(System.out::println);
// flatMap(Function f) - 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连成一个流
// flatMap 先提取属性放入一个比较小的流,然后再将所有的流合并为一个流。有一种 “聚沙成塔” 的感觉。
}
中间操作–排序
/**
* 排序
*/
public void test3() {
// sorted() - 自然排序
List<Integer> list = Arrays.asList(12, 78, 34, 72, 17, 83);
list.stream().sorted().forEach(System.out::println);
// 会抛异常,原因:Employee对象没有实现Comparable接口
List<Employee> employees = EmployeeData.getEmployees();
// employees.stream().sorted().forEach(System.out::println);
// sorted(Comparator comparator) - 定制排序
// 按照年龄排序
employees.stream().sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())).forEach(System.out::println);
// 先按照年龄排序,然后按照ID排序
employees.stream().sorted(
(e1, e2) -> {
int compareResult = Integer.compare(e1.getAge(), e2.getAge());
if (compareResult == 0) {
return compareResult;
} else {
return Integer.compare(e1.getId(), e2.getId());
}
}
).forEach(System.out::println);
}
终止操作
public void test1() {
List<Employee> employees = EmployeeData.getEmployees();
// allMatch(Predict p) -- 检查是否匹配所有元素
boolean result = employees.stream().allMatch(age -> age.getAge() > 18);
// anyMatch(Predict p) - 检查是否至少匹配一个元素
boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() < 100);
// noneMatch(Predicate p) - 检查是否没有匹配的元素
boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startsWith("雷"));
// findFirst - 返回第一个元素
Optional first = employees.stream().findFirst();
// count - 返回流中元素的总个数
long count = employees.stream().limit(6).count();
// max(Comparator c) - 返回流中的最大值
Optional<Double> max = employees.stream().map(Employee::getSalary).max(Double::compare);
// min(Comparator c) - 返回流中的最小值
Optional<Employee> min = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
}