Stream API

Stream API的使用

  • 前言
  • 一、Stream API说明
    • 1.1、引入说明
      • 1.1.1、为什么要使用Stream API
      • 1.1.2、什么是 Stream
    • 1.2、使用说明
      • 1.2.1、Stream 的操作三个步骤
  • 二、Stream流的使用
    • 数据准备
    • 2.1、四种创建方式
    • 2.2、常用中间操作
    • 2.3、终止操作


前言

个人笔记,仅供参考。


一、Stream API说明

1.1、引入说明

  • Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API
  • Stream API ( java.util.stream) 把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
  • Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

1.1.1、为什么要使用Stream API

  • 实际开发中,项目中多数数据源都来自于Mysql,Oracle等。但现在数据源可以更多了,有MongDB,Radis等,而这些NoSQL的数据就需要Java层面去处理。
  • Stream 和 Collection 集合的区别:Collection 是一种静态的内存数据结构,而 Stream 是有关计算的。前者是主要面向内存,存储在内存中,后者主要是面向 CPU,通过 CPU 实现计算。

1.1.2、什么是 Stream

是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。

“集合讲的是数据,Stream讲的是计算!”
注意:

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

1.2、使用说明

1.2.1、Stream 的操作三个步骤

  • 1- 创建 Stream
    一个数据源(如:集合、数组),获取一个流
  • 2- 中间操作
    一个中间操作链,对数据源的数据进行处理
  • 3- 终止操作(终端操作)
    一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用

二、Stream流的使用

数据准备

public class EmployeeData {
	
	public static List<Employee> getEmployees(){
		List<Employee> list = new ArrayList<>();
		
		list.add(new Employee(1001, "马化腾", 34, 6000.38));
		list.add(new Employee(1002, "马云", 12, 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.32));
		list.add(new Employee(1008, "扎克伯格", 35, 2500.32));
		
		return list;
	}
	
}
public class Employee {

	private int id;
	private String name;
	private int age;
	private double 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;
	}

	public Employee() {

	}

	public Employee(int id) {

		this.id = id;
	}

	public Employee(int id, String name) {
		this.id = id;
		this.name = name;
	}

	public Employee(int id, String name, int age, double salary) {

		this.id = id;
		this.name = name;
		this.age = age;
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "Employee{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", 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;

		if (id != employee.id)
			return false;
		if (age != employee.age)
			return false;
		if (Double.compare(employee.salary, salary) != 0)
			return false;
		return name != null ? name.equals(employee.name) : employee.name == null;
	}

	@Override
	public int hashCode() {
		int result;
		long temp;
		result = id;
		result = 31 * result + (name != null ? name.hashCode() : 0);
		result = 31 * result + age;
		temp = Double.doubleToLongBits(salary);
		result = 31 * result + (int) (temp ^ (temp >>> 32));
		return result;
	}
}

2.1、四种创建方式

/*1、通过集合*/
    @Test
    public void test1(){
        List<Employee> employeeList = new ArrayList<>();
        /*  创建顺序流:default Stream stream;  */
        Stream<Employee> stream = employeeList.stream();
        /*  创建并行流:default Stream parallelStream();   */
        Stream<Employee> parallelStream = employeeList.parallelStream();
    }
    /*2、通过数组*/
    @Test
    public void test2(){

        /*static  Stream stream(T[] array): 返回一个流*/
        Integer[] arr = {1,2,1,2,3,5};
        Stream<Integer> stream = Arrays.stream(arr);

        int[] intArr = {1,2,5,8,5,2};
        IntStream stream1 = Arrays.stream(intArr);
    }
    /*3、通过Stream的of()*/
    @Test
    public void tes3(){
        /*public static Stream of(T... values) : 返回一个流*/
        Stream<String> stream = Stream.of("AA", "BB", "CC");
    }
    /*4、创建无限流*/
    @Test
    public void test4(){
        /* 迭代
        public static Stream iterate(final T seed, final UnaryOperator f)*/

        /* 生成
        public static Stream generate(Supplier s)*/
    }

2.2、常用中间操作

/* 一、筛选与切片*/
    @Test
    public void test1(){

        List<Employee> employeeList = EmployeeData.getEmployees();
        Stream<Employee> stream = employeeList.stream();

        /* 1、filter(Predicate P),接收lambda,从流中过滤出符合条件的数据。
        filter查询出员工中工资大于7000的员工
        */
        stream.filter(employee -> employee.getSalary() > 7000 ).forEach(System.out::println);
        System.out.println();

        /* 2、limit(n)-截断流,使其元素不超过给定数量
        查询工资大于7000的前两条数据
        */
        employeeList.stream().filter(employee -> employee.getSalary() > 7000 ).limit(2).forEach(System.out::println);
        System.out.println();

        /* 3、skip(n)-截断流,跳过前n个数据
        查询工资大于7000的前两条数据之外的数据
        */
        employeeList.stream().filter(employee -> employee.getSalary() > 7000 ).skip(2).forEach(System.out::println);

        /*
        * 4、distinct()-筛选,通过流生成的hashcode和equals()
        根据姓名去重
        */
        employeeList.add(new Employee(1006, "比尔盖茨", 42, 9500.43));
        employeeList.add(new Employee(1007, "任正非", 26, 4333.32));
        employeeList.add(new Employee(1008, "扎克伯格", 35, 2500.32));
        employeeList.stream().distinct().forEach(System.out::println);
    }
    /* 二、映射*/
    @Test
    public void test(){
        List<String> list = Arrays.asList("A", "BB", "CCC");
        /* 1、map(Function f):接受一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每一个元素上
        将集合中的全部元素转换成小写
        */
        list.stream().map(String::toLowerCase).forEach(System.out::println);
        list.stream().map(str -> str.toLowerCase()).forEach(System.out::println);
        System.out.println();
        /*
        * 获取员工中的员工名称长度大于三的员工
        */
        List<Employee> employeeList = EmployeeData.getEmployees();
        employeeList.stream().filter(emp -> emp.getName().length() > 3).forEach(System.out::println);
        /*
         * 获取员工中的员工名称长度大于三的员工姓名
         */
        employeeList.stream().filter(emp -> emp.getName().length() > 3).map(emp -> emp.getName()).forEach(System.out::println);
        System.out.println();
        employeeList.stream().map(emp -> emp.getName()).filter(emp -> emp.length() > 3).forEach(System.out::println);
        System.out.println();
        employeeList.stream().map(Employee::getName).filter(emp -> emp.length() > 3).forEach(System.out::println);


    }
    /* 三、排序*/
    @Test
    public void test3(){

        Integer[] intArr = {22,5,6,8,52,54,63};
        String[] strArr = {"AA","JJ","BB","GG"};
        /* sorted()--自然排序*/
        Arrays.stream(intArr).sorted().forEach(System.out::println);
        Arrays.stream(strArr).sorted().forEach(System.out::println);

        /* sorted(Comparator com)--定制排序*/
        List<Employee> employeeList = EmployeeData.getEmployees();
        employeeList.stream().sorted((e1,e2) -> (int) (e1.getSalary() - e2.getSalary())).forEach(System.out::println);

        Arrays.stream(intArr).sorted((s1, s2) -> -s1.compareTo(s2)).forEach(System.out::println);

    }

2.3、终止操作

/*一、匹配与查找*/
    @Test
    public void test1(){
        List<Employee> employeeList = EmployeeData.getEmployees();
        // allMatch(Predicate p) 是否所有员工的年龄都大于30
        System.out.println(employeeList.stream().allMatch(e -> e.getAge() > 30));
        // anyMatch(Predicate p) 是否存在员工年龄大于40的员工
        System.out.println(employeeList.stream().anyMatch(emp -> emp.getAge() > 40));
        // 是否有员工工资大于一万的数据
        System.out.println(employeeList.stream().anyMatch(emp -> emp.getSalary() > 10000));
        // findFirst(Predicate p) 返回符合条件的第一个元素
        System.out.println(employeeList.stream().filter(emp -> emp.getName().length() > 3).findFirst().get());
    }
    @Test
    public void test2(){
        List<Employee> employeeList = EmployeeData.getEmployees();
        // count() 返回流中元素的总个数
        // 统计工资大于7000的员工的个数
        System.out.println(employeeList.stream().filter(emp -> emp.getSalary() > 7000).count());

        // max(Comparator com) 返回流中元素最大值
        // 返回流中最高的工资
        System.out.println(employeeList.stream().map(employee -> employee.getSalary()).max(Double::compare).get());

        // min(Comparator com) 返回流中元素最小值
        // 返回流中最低的工资的员工信息
        System.out.println(employeeList.stream().min(Comparator.comparingDouble(Employee::getSalary)).get());

        //forEach(Consumer c) 内部迭代
//        employeeList.stream().forEach(System.out::println);

        // 针对于集合java 8 增加了forEach()方法
        employeeList.forEach(System.out::println);
        
    }
    /* 二、归约 */
    @Test
    public void test3(){
        List<Employee> employeeList = EmployeeData.getEmployees();
        // reduce(T identity,BinaryOperator) - 将流中的元素反复结合起来得到一个新值,返回T
        // 计算1-10的自然数之和
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        System.out.println(list.stream().reduce(0, (x, y) -> x + y));
        System.out.println(list.stream().reduce(0, (x, y) -> Integer.sum(x, y)));
        System.out.println(list.stream().reduce(0, Integer::sum));

        // reduce(BinaryOperator) - 将流中的元素反复结合起来得到一个新值,返回Optional
        // 计算所有员工的工资之和
        System.out.println(employeeList.stream().map(Employee::getSalary).reduce(0.0, (x, y) -> x + y));
        System.out.println(employeeList.stream().map(Employee::getSalary).reduce(0.0, (x, y) -> Double.sum(x, y)));
        System.out.println(employeeList.stream().map(Employee::getSalary).reduce(0.0, Double::sum));

    }
    /* 三、收集 */
    @Test
    public void test4(){
        List<Employee> employeeList = EmployeeData.getEmployees();
        // collect(Collect c) 将流转换为其他形式。接收一个Collector接口的实现,用于给Stream流中元素做汇总的方法

        // 查找工资大于6000的员工,并返回一个新的list或者set
        System.out.println(employeeList.stream().filter(emp -> emp.getSalary() > 70000).collect(Collectors.toList()));
        Set<Employee> set = employeeList.stream().filter(emp -> emp.getSalary() > 7000).collect(Collectors.toSet());
        set.stream().forEach(System.out::println);

        // 按照员工的年龄进行排序,返回到一个新的list中
        System.out.println(employeeList.stream().sorted((e1, e2) -> (int) (e1.getSalary() - e2.getSalary())).collect(Collectors.toList()));
    }

你可能感兴趣的:(Stream)