JDK1.8 新特性之Stream的常用方法1

Stream的三个操作步骤:

    1. 创建Stream: 一个数据源(如:集合、 数组),获取一个流

    2. 中及操作: 一个中间操作链,对数据源的数据进行处理

    3. 终止操作(终端操作):一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用。

 

 创建Stream的常见方式: 详情查看 demo1

 

 中间操作的常用方法:

     filter --- 接收Lambda,从流中排除某些元素

     limit  --- 截断流,使其元素不超过给定数量。

     skip(n)--- 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit互补

     distinct --- 筛选,通过流所生成元素的hashCode()和equals去除重复元素。

     map --- 接收Lambda,将元素转换成其他形式或提取信息.接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素.

     flatMap --- 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

     sorted(): 自然排序(Comparable)

     sorted(Comparator com): 定制排序

 

终止操作的常用方法:点我

 

话不多说,上码

员工基础类:

import lombok.Data;
import java.util.Objects;

// 员工信息
@Data
public class Employee {
    private String name; // 姓名
    private Integer age; // 年龄
    private Double salary; // 工资
    private Status status; // 状态

    public enum Status {
        FREE,
        BUSY,
        VOCATION;
    }

    public Employee() {}

    public Employee(String name, Integer age, Double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public Employee(String name, Integer age, Double salary, Status status) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.status = status;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                ", status=" + status +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return Objects.equals(name, employee.name) &&
                Objects.equals(age, employee.age) &&
                Objects.equals(salary, employee.salary);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, salary);
    }
}

测似用例:

import com.sarj.streetlamp.optional.Employee;
import org.junit.Test;
import java.util.*;
import java.util.stream.Stream;

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

 创建Stream的常见方式: 详情查看 demo1

 中间操作的常用方法:
     filter --- 接收Lambda,从流中排除某些元素
     limit  --- 截断流,使其元素不超过给定数量。
     skip(n)--- 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit互补
     distinct --- 筛选,通过流所生成元素的hashCode()和equals去除重复元素。
     map --- 接收Lambda,将元素转换成其他形式或提取信息.接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素.
     flatMap --- 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
     sorted(): 自然排序(Comparable)
     sorted(Comparator com): 定制排序
 */
public class StreamTest1 {
    // 创建Stream的常见方式
    @Test
    public void demo1() {
        // 方式一: 通过Collection系列集合提供的stream() 或 parallelStream()
        // stream():获取的是串行流, 串行(可以理解为: 一个一个执行操作动作)
        // parallelStream(): 获取的是并行流, 并行(可以理解为:可以同时执行多个操作动作)
        List list = new ArrayList<>();
        Stream stream1 = list.stream();
        Stream stream2 = list.parallelStream();

        // 方式二: 通过Arrays中的静态方法stream()获取数组流
        String[] strs = new String[2];
        Stream stream3 = Arrays.stream(strs);

        // 3. 通过Stream类中的静态方法of(String... values): 它可以接收任意数量的参数
        Stream stream4 = Stream.of(1, 2, 3);
        Stream stream5 = Stream.of(strs);
        Stream> stream6 = Stream.of(list);

        // 4. 创建无限流
        // 迭代
        Stream stream7 = Stream.iterate(0, (x) -> x + 2); // seed是起始位置, 从 seed开始, 然后一直执行 x + 2操作
        stream7.limit(10).forEach(System.out::println); // limit:相当于中间操作; forEach相当于终止操作(中间操作讲解, 别急,静下心)

        // 生成
        Stream stream8 = Stream.generate(Math::random);
        stream8.limit(5).forEach(System.out::println); // limit:相当于中间操作; forEach相当于终止操作(中间操作讲解, 别急,静下心)
    }

    // 公用数据
    List emps = Arrays.asList(
            new Employee("张三", 18, 9999.99, Employee.Status.FREE),
            new Employee("李四", 58, 5555.55, Employee.Status.BUSY),
            new Employee("王五", 26, 3333.33, Employee.Status.VOCATION),
            new Employee("赵六", 36, 6666.66, Employee.Status.FREE),
            new Employee("赵六", 36, 6666.66, Employee.Status.FREE),
            new Employee("田七", 12, 8888.88, Employee.Status.BUSY)
    );

    // 中间操作: 不会执行任何操作 - start
    /**
     * filter测试用例
     * filter --- 接收Lambda,从流中排除某些元素
     */
    @Test
    public void demo2() {
        // 外部迭代:list.iterator
        // 内部迭代: 迭代操作由StreamAPI完成
        System.out.println(" ------ 中间操作之过滤 ----------");
        // 1. 创建流
        Stream stream1 = emps.stream();
        // 2. 中间操作之过滤, 过滤出年龄大于35的员工
        Stream stream2 = stream1.filter((e) -> {
            System.out.println("过滤...");
            return e.getAge() > 35;
        }); // 要是没有终止操作,不会打印“中间操作”log。。。
        // 3. 当执行终止操作时,会讲一系列中间操作一次性执行, 即"惰性求值"

        stream2.forEach(System.out::println);
        System.out.println("---- 另一种实现: 建议采用这种方式,看的爽... ------");
        // 另一种实现
        emps.stream().filter((e) -> {
            System.out.println("过滤2....");
            return e.getAge() > 35;
        }).forEach(System.out::println);
    }

    /**
     * limit、skip、distinct测试用例
     * limit  --- 截断流,使其元素不超过给定数量。
     * skip(n)--- 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit互补
     * distinct --- 筛选,通过流所生成元素的hashCode()和equals去除重复元素。
     */
    @Test
    public void demo3() {
        System.out.println("--------- 中间操作之截断流(limit),实现1");
        // 1. 创建流
        Stream stream1 = emps.stream();
        // 2. 中间操作之截断流, 截取一个员工
        Stream stream2 = stream1.limit(1);
        // 3. 终止操作
        stream2.forEach(System.out::println);

        System.out.println("--------- 中间操作之截断流(limit),实现2");
        emps.stream().limit(1).forEach(System.out::println);

        System.out.println("--------- 中间操作之跳过元素(skip),实现1");
        // 1. 创建流
        Stream stream3 = emps.stream();
        // 2. 中间操作之跳过元素, 跳过前两个员工
        Stream stream4 = stream3.skip(2);
        // 3. 终止操作
        stream4.forEach(System.out::println);
        System.out.println("--------- 中间操作之跳过元素(skip),实现2");
        emps.stream().skip(2).forEach(System.out::println);

        System.out.println("--------- 筛选,通过流所生成元素的hashCode()和equals去除重复元素, 实现1");
        // 1. 创建流
        Stream stream5 = emps.stream();
        // 2. 中间操作之筛选,通过流所生成元素的hashCode()和equals去除重复元素
        Stream stream6 = stream5.distinct();
        // 3. 终止操作
        stream6.forEach(System.out::println);

        System.out.println("--------- 筛选,通过流所生成元素的hashCode()和equals去除重复元素, 实现2");
        emps.stream().distinct().forEach(System.out::println);
    }

    // filter, limit, skip, distinct联合使用
    @Test
    public void demo4() {
        // 过滤出大于15的员工,然后跳过第一个,再去重复的,最后截取四个员工的信息并输出
        System.out.println(" ----- filter, limit, skip, distinct联合使用");
        emps.stream().filter((e) -> e.getAge() > 15).skip(1).distinct().limit(4).forEach(System.out::println);
    }

    /**
     * map测试用例:
     * map --- 接收Lambda,将元素转换成其他形式或提取信息.接收一个函数作为参数,该函数会被应用到每个元素上,
     *             并将其映射成一个新的元素.
     */
    @Test
    public void demo5() {
        List strList = Arrays.asList("aaa", "bbb", "ccc", "ddd");

        // 1. 创建流
        Stream stream = strList.stream();
        // 2. 中间操作, 将列表中的元素都转为大写
        Stream stream1 = stream.map((str) -> str.toUpperCase());
        // 3. 终止操作
        stream1.forEach(System.out::println);

        // 等同于上面三步操作
        System.out.println(" -------------- 简化代码方式 ------------");
        strList.stream().map((str) -> str.toUpperCase()).forEach(System.out::println);

        System.out.println("----------------------");
        // 1. 创建流
        Stream stream2 = emps.stream();
        // 2. 中间操作, 只获取员工中的名字这个信息
        Stream stream3 = stream2.map(Employee::getName);
        stream3.forEach(System.out::println);
        // 等同于上面三步操作
        System.out.println(" -------------- 简化代码方式 ------------");
        emps.stream().map(Employee::getName).forEach(System.out::println);
    }

    /**
     * flatMap测试用例
     * flatMap --- 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
     */
    @Test
    public void demo6() {
        List strList = Arrays.asList("aaa", "bbb", "ccc", "ddd");

        // 使用map方式
        Stream> stream1 = strList.stream().map(StreamTest1::filterCharacter); // {
    {a,a,a}, {b,b,b}}
        stream1.forEach(sm -> {
            sm.forEach(System.out::println);
        });

        // 使用flatMap方式
        Stream stream2 = strList.stream();
        Stream stream3 = stream2.flatMap(StreamTest1::filterCharacter); // {a,a,a, b,b,b}
        stream3.forEach(System.out::println);
    }

    public static Stream filterCharacter(String str) {
        List list = new ArrayList<>();

        for (Character ch : str.toCharArray()) {
            list.add(ch);
        }
        return list.stream();
    }

    /**
    排序之sorted测试用例:
         sorted(): 自然排序(Comparable)
         sorted(Comparator com): 定制排序
     */
    @Test
    public void demo7() {
        // 以下都写简化代码哈,根据上面的多次分解操作Stream应该都会了哈。
        System.out.println("---------  自然排序  ------------");
        List strList = Arrays.asList("ccc", "aaa", "bbb", "ddd");
        strList.stream().sorted().forEach(System.out::println); // 自然排序

        System.out.println("---------  自定义排序  ------------");
        emps.stream().sorted((e1, e2) -> {
            if (e1.getAge().equals(e2.getAge())) { // 当年龄相同时,比较姓名
                return e1.getName().compareTo(e2.getName());
            }
            return e1.getAge().compareTo(e2.getAge());
        }).forEach(System.out::println);
    }
    // 中间操作: 不会执行任何操作 - end
}

 

你可能感兴趣的:(JAVASE)