主页 > 人工智能  > 

【Java】StreamAPI

【Java】StreamAPI
概述

Stream API ( java.util.stream) 把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。 也可以使用Stream API来并行执行操作。简言之,Stream API提供了一种高效且易于使用的处理数据的方式。

实际开发中,项目中多数数据源都来自于Mysql,Oracle等。但现在数据源可以更多了,有MongDB,Radis等,而这些NoSQL的数据就需要Java层面去处理。

Stream和 Collection集合的区别:Collection是一种静态的内存数据结构,而 Stream是有关计算的。前者是主要面向内存,存储在内存中, 后者主要是面向 CPU,通过CPU 实现计算。

总之,Stream到底是一种数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,Stream讲的是计算!”

注意:

Stream自己不会存储元素。Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。 三个步骤

Stream操作分为三个步骤:

创建Stream中间操作终止操作

创建Stream

方式一:Java8中的Collection接口被扩展,提供了两个获取流的方法

default Stream stream() : 返回一个顺序流default Stream parallelStream() : 返回一个并行流 List<Employee> employees = EmployeeData.getEmployees(); // default Stream<E> stream() : 返回一个顺序流 Stream<Employee> stream = employees.stream(); //default Stream<E> parallelStream() : 返回一个并行流 Stream<Employee> parallelStream = employees.parallelStream();

方式二:Java8中的Arrays的静态方法stream()可以获取数组流

static Stream stream(T[] array): 返回一个流

重载形式,能够处理对应基本类型的数组:

public static IntStream stream(int[] array) public static LongStream stream(long[] array) public static DoubleStream stream(double[] array) int[] arr = new int[]{1, 3, 4, 5, 5}; IntStream stream = Arrays.stream(arr); Employee[] employees = new Employee[]{new Employee(222, "Tom"), new Employee(33)}; Stream<Employee> stream1 = Arrays.stream(employees);

方式三:通过Stream的of()

可以调用Stream类静态方法of(), 通过显示值创建一个流。它可以接收任意数量的参数。

public static Stream of(T... values) : 返回一个流

Stream<Integer> stream = Stream.of(1, 3, 4, 6, 4); 中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

筛选与切片 方法描述filter(Predicate p)接收Lambda,从流中排除某些元素distinct()筛选,通过流所生成元素的hashCode()和equals()去除重复元素limit(Iong maxSize)截断流,使其元素不超过给定数量skip(long n)跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补

示例代码:

// filter: 查询员工表中薪资大于7000的员工信息 list.stream().filter(employee -> employee.getSalary() > 7000).forEach(System.out::println); System.out.println(); // limit: 查询前3条记录 list.stream().limit(3).forEach(System.out::println); System.out.println(); // skip: 跳过前3条记录 list.stream().skip(3).forEach(System.out::println); System.out.println(); // distinct: 筛选 list.add(new Employee(1002, "马云", 12, 9876.12)); list.add(new Employee(1002, "马云", 12, 9876.12)); list.add(new Employee(1002, "马云", 12, 9876.12)); list.add(new Employee(1002, "马云", 12, 9876.12)); for (Employee employee : list) { System.out.println(employee); } System.out.println(); list.stream().distinct().forEach(System.out::println); 映射

map(Function f):接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

示例代码:

// 获取员工姓名长度大于3的员工的姓名 // 先映射,后筛选,lambda写法 list.stream().map(employee -> employee.getName()).filter(str -> str.length() > 3).forEach(System.out::println); // 先映射,后筛选,方法引用写法 list.stream().map(Employee::getName).filter(str -> str.length() > 3).forEach(System.out::println); // 先筛选,后映射,lambda写法 list.stream().filter(employee -> employee.getName().length() > 3).map(employee -> employee.getName()).forEach(System.out::println); // 先筛选,后映射,方法引用写法 list.stream().filter(employee -> employee.getName().length() > 3).map(Employee::getName).forEach(System.out::println); 排序

sorted():产生一个新流,其中按自然顺序排序

sorted(Comparator com):产生一个新流,其中按比较器顺序排序

示例代码:

// 新定义一个list进行自然排序 List<Integer> list1 = Arrays.asList(12, 33, 35, 32, 22, 11, 55, 33); list1.stream().sorted().forEach(System.out::println); // 按员工年龄升序排序 list.stream().sorted((e1, e2) -> e1.getAge() - e2.getAge()).forEach(System.out::println); 终止操作

一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用。注意:流进行了终止操作后,不能再次使用。

匹配与查找 方法描述allMatch(Predicate p)检查是否匹配所有元素anyMatch(Predicate p)检查是否至少匹配一个元素noneMatch(Predicate p)检查是否没有匹配所有元素findFirst()返回第一个元素findAny()返回当前流中的任意元素count()返回流中元素总数max(Comparator c)返回流中最大值min(Comparator c)返回流中最小值forEach(Consumer c)内部迭代

示例代码:

// 是否所有员工年龄都大于18 boolean allMatch = list.stream().allMatch(employee -> employee.getAge() > 18); System.out.println(allMatch); // 是否存在员工的薪水大于10000 boolean anyMatch = list.stream().anyMatch(employee -> employee.getSalary() > 10000); System.out.println(anyMatch); // 返回最高的工资 Optional<Double> maxSalary = list.stream().map(Employee::getSalary).max(Double::compareTo); System.out.println(maxSalary.get()); // 返回最低工资的员工 Optional<Employee> employee = list.stream().min((emp1, emp2) -> Double pare(emp1.getSalary(), emp2.getSalary())); System.out.println(employee.get()); 规约

reduce(T iden, BinaryOperator b):可以将流中元素反复结合起来,得到一个值。返回T。iden可以理解为初始值。

reduce(BinaryOperator b):可以将流中元素反复结合起来,得到一个值。返回Optional<T>

备注:map和reduce的连接通常称为map-reduce模式,因Google用它来进行网络搜索而出名。

示例代码:

// 计算所有员工工资总和 Double totalSalary1 = list.stream().map(Employee::getSalary).reduce(0.0, (d1, d2) -> d1 + d2); // 注意这种方式返回值类型会有Optional类包裹 Optional<Double> totalSalary2 = list.stream().map(Employee::getSalary).reduce(Double::sum); System.out.println(totalSalary1); System.out.println(totalSalary2.get()); 收集

collect(Collector c):将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法

Collector接口中方法的实现决定了如何对流执行收集的操作(如收集到List、Set、Map)。另外,Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例, 具体方法与实例如下表:

方法返回类型作用toListList<T>把流中元素收集到ListtoSetSet<T>把流中元素收集到SettoCollectionCollection<T>把流中元素收集到创建的集合

例如:

list.stream().collect(Collections.toList())

list.stream().collect(Collections.toSet())

list.stream().collect(Collections.toCollection(ArrayList::new))

示例代码:

// 查找工资大于6000的员工,结果返回为list List<Employee> empList = list.stream().filter(emp -> emp.getSalary() > 6000).collect(Collectors.toList()); empList.forEach(System.out::println); // 查找工资大于6000的员工,结果返回为set Set<Employee> empSet = list.stream().filter(emp -> emp.getSalary() > 6000).collect(Collectors.toSet()); empSet.forEach(System.out::println); 附

Employee类

public class Employee { private int id; private String name; private int age; private double salary; public Employee() { } public Employee(int id, String name, int age, double salary) { this.id = id; this.name = name; this.age = age; this.salary = salary; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Employee employee = (Employee) o; return id == employee.id && age == employee.age && Double pare(employee.salary, salary) == 0 && Objects.equals(name, employee.name); } @Override public int hashCode() { return Objects.hash(id, name, age, salary); } @Override public String toString() { return "Employee{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}'; } }

以及随便创建的list数据

static ArrayList<Employee> list = new ArrayList<>(); static { list.add(new Employee(1001, "马化腾", 34, 6000.38)); list.add(new Employee(1002, "马云", 2, 9876.12)); list.add(new Employee(1003, "刘强东", 33, 3000.82)); list.add(new Employee(1004, "雷军", 26, 7657.37)); list.add(new Employee(1005, "李彦宏", 65, 5555.32)); list.add(new Employee(1006, "比尔盖茨", 42, 9500.43)); list.add(new Employee(1007, "任正非", 26, 4333.33)); list.add(new Employee(1008, "扎克伯格", 35, 2500.32)); }
标签:

【Java】StreamAPI由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【Java】StreamAPI