第13章_Java8的新特性

13.Java8的新特性

13.1 Lambda表达式

public class Main {
/*
1.Lambda表达式的基本语法:
    1.1 举例: (o1,o2) -> Integer.compare(o1,o2);
    1.2 格式:
        1.2.1 ->:lambda操作符
        1.2.2 ->左边:lambda形参列表 (即接口中抽象方法的形参列表)
        1.2.3 ->右边:lambda体 (即重写的抽象方法的方法体)
2.总结:
    2.1 ->左边:
        2.1.1 如果lambda形参列表有且只有一个参数,其一对()可以省略
        2.1.2 lambda形参列表的参数类型可以省略(类型推断:给出泛型类型就是泛型类型,没有给出泛型类型就是Object)
    2.2 ->右边:
        2.2.1 lambda体应该使用一对{}包裹;
        2.2.2 如果lambda体只有一条执行语句,可以省略这一对{}:
            2.2.2.1 如果这条语句是return语句,可以省略return关键字,但是要和{}同时省略或同时不省略
            2.2.2.2 如果这条语句是其他语句,如System.out.println();,则一定不可以省略,且与是否省略这一对{}无关
3.示例:
 */
    @Test
    public void test1(){
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable1");
            }
        };
        runnable1.run();
        System.out.println("******");
        Runnable runnable2=()-> System.out.println("runnable2");;
        runnable2.run();
    }
    @Test
    public void test2(){
        Consumer<String> consumer1 = new Consumer<>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer1.accept("consumer1");
        System.out.println("******");
        Consumer<String> consumer2=s-> System.out.println(s);
        consumer2.accept("consumer2");
    }

    @Test
    public void test3(){
        Comparator<Integer> comparator1 = new Comparator<>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };
        System.out.println(comparator1.compare(12,21));
        System.out.println("*******");
        Comparator<Integer> comparator2 = (o1,o2) -> o1.compareTo(o2);
        System.out.println(comparator2.compare(12,21));

        System.out.println();
        Comparator<Integer> comparator3 = new Comparator<>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println("diudiudiudiudiu!");
                return o1.compareTo(o2);
            }
        };
        System.out.println(comparator3.compare(12,21));
        System.out.println("*******");
        Comparator<Integer> comparator4 = (o1,o2) -> {
            System.out.println("diudiudiudiudiu!");
            return o1.compareTo(o2);
        };
        System.out.println(comparator4.compare(12,21));
    }
}

13.2 函数式接口

/*
1.函数式接口的说明
    1.1 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口
    1.2 我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口
    1.3 Lambda表达式的本质:作为函数式接口的实例
2.在java.util.function包下定义了丰富的函数式接口,以下是4个基本的函数式接口:
*/  
public class Main {
/*
    2.1 消费型接口:Consumer<T>   void accept(T t)
 */
    @Test
    public void test1(){
        Consumer<Double> consumer=a->System.out.println(a);
        consumer.accept(100.0);
    }
/*
    2.2 供给型接口:Supplier<T>   T get()
 */
    @Test
    public void test2(){
        Supplier<String> supplier=()->"hh";
        String s = supplier.get();
        System.out.println(s);
    }
/*
    2.3 函数型接口:Function<T,R>   R apply(T t)
 */
    @Test
    public void test3(){
        Function<String,Integer> function=s->Integer.parseInt(s);
        Integer apply = function.apply("12");
        System.out.println(apply);
    }
/*
    2.4 断定型接口:Predicate<T>    boolean test(T t)
 */
    @Test
    public void test4(){
        List<String> list = Arrays.asList("北京", "南京", "天津", "东京", "西京", "普京");
        List<String> filterString = filterString(list, s -> s.contains("京"));
        for (String s : filterString) {
            System.out.println(s);
        }
    }
    public List<String> filterString(List<String> list, Predicate<String> predicate){
        ArrayList<String> filterList = new ArrayList<>();
        for (String s : list) {
            if(predicate.test(s)) {
                filterList.add(s);
            }
        }
        return filterList;
    }
}
/*
3.总结
	3.1 何时使用lambda表达式?
		当需要对一个函数式接口实例化的时候,可以使用lambda表达式
	3.2 何时使用给定的函数式接口?
    	如果我们开发中需要一个函数式接口,首先看看给定的函数式接口是否能满足需求,如果能,则直接调用即可。
*/

13.3 方法引用

public class Main {
/*
1.理解:方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例。
2.使用情境:当Lambda表达式的操作已经有了实现的方法,就可以使用方法引用!
3.格式:类(或对象) :: 方法名
4.分为如下的三种情况:
    4.1 对象 :: 非静态方法
    4.2 类 :: 静态方法
    4.3 类 :: 非静态方法
5.要求:
    5.1 情况1和情况2:要求接口中抽象方法的形参列表和返回值类型与引用方法的形参列表和返回值类型相同!
    5.2 情况3:要求接口中抽象方法的第一个参数是引用方法的调用者,并且第二个参数是引用方法的参数(或无参数)
6.使用建议:
    6.1 如果给函数式接口提供实例,恰好满足方法引用的使用情境,大家就可以考虑使用方法引用给函数式接口提供实例。
    6.2 如果大家不熟悉方法引用,那么还可以使用lambda表达式
7.使用举例:
 */
    //情况一:对象 :: 实例方法
    //Consumer<T>中的:void accept(T t)
    //PrintStream中的:void println(String x)
    @Test
    public void test1() {
        Consumer<String> con1 = str -> System.out.println(str);
        con1.accept("con1");
        System.out.println("*******************");
        Consumer<String> con2=System.out::println;
        con2.accept("con2");
    }

    //Supplier<T>中的:T get()
    //Employee中的:String getName()
    @Test
    public void test2() {
        Employee emp = new Employee(1001,"Tom",23,5600);

        Supplier<String> sup1 = () -> emp.getName();
        System.out.println(sup1.get());

        System.out.println("*******************");
        Supplier<String> sup2=emp::getName;
        System.out.println(sup2.get());
    }

    //情况二:类 :: 静态方法
    //Comparator<T>中的:int compare(T o1, T o2)
    //Integer中的:static int compare(int x, int y)
    @Test
    public void test3() {
        Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2);
        System.out.println(com1.compare(12,21));

        System.out.println("*******************");
        Comparator<Integer> com2=Integer::compare;
        System.out.println(com2.compare(12, 21));
    }

    //Function<T, R>中的:R apply(T t)
    //Math中的:static long round(double a)
    @Test
    public void test4() {
        Function<Double,Long> func1 = d -> Math.round(d);
        System.out.println(func1.apply(12.3));

        System.out.println("*******************");
        Function<Double,Long> func2=Math::round;
        System.out.println(func2.apply(12.3));
    }

    //情况三:类 :: 实例方法
    //Comparator<T>中的:int compare(T o1, T o2)
    //String中的:int compareTo(String anotherString)
    @Test
    public void test5() {
        Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
        System.out.println(com1.compare("abc","abd"));

        System.out.println("*******************");
        Comparator<String> com2=String::compareTo;
        System.out.println(com2.compare("abc","abd"));
    }

    //BiPredicate<T, U>中的:boolean test(T t, U u);
    //String中的:boolean equals(Object anObject)
    @Test
    public void test6() {
        BiPredicate<String,String> pre1 = (s1, s2) -> s1.equals(s2);
        System.out.println(pre1.test("abc","abc"));

        System.out.println("*******************");
        BiPredicate<String,String> pre2 = String :: equals;
        System.out.println(pre2.test("abc","abd"));
    }

    //Function<T, R>中的:R apply(T t)
    //Employee中的:String getName();
    @Test
    public void test7() {
        Employee employee = new Employee(1001, "Jerry", 23, 6000);

        Function<Employee,String> func1 = e -> e.getName();
        System.out.println(func1.apply(employee));

        System.out.println("*******************");
        Function<Employee,String> func2 = Employee::getName;
        System.out.println(func2.apply(employee));
    }

}
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() {
        System.out.println("Employee().....");
    }

    public Employee(int id) {
        this.id = id;
        System.out.println("Employee(int 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;
    }
}

13.4 构造器引用与数组引用

public class Main {
/*
1.构造器引用格式:类名::new
2.构造器引用的使用要求:要求接口中抽象方法的形参列表和构造器的形参列表一致,抽象方法的返回值类型即为构造器所属类
3.构造器引用举例:
 */
    //Supplier<T>中的:T get()
    //Employee的空参构造器:Employee()
    @Test
    public void test1(){

        Supplier<Employee>  sup1 = () -> new Employee();
        System.out.println(sup1.get());

        System.out.println("*******************");

        Supplier<Employee>  sup2 = Employee :: new;
        System.out.println(sup2.get());
    }

    //Function<T, R>中的:R apply(T t)
    //Employee的构造器:Employee(int id)
    @Test
    public void test2(){
        Function<Integer,Employee> func1 = id -> new Employee(id);
        Employee employee = func1.apply(1001);
        System.out.println(employee);

        System.out.println("*******************");

        Function<Integer,Employee> func2 = Employee :: new;
        Employee employee1 = func2.apply(1002);
        System.out.println(employee1);

    }

    //BiFunction<T, U, R>中的:R apply(T t,U u)
    //Employee的构造器:Employee(int id, String name)
    @Test
    public void test3(){
        BiFunction<Integer,String,Employee> func1 = (id,name) -> new Employee(id,name);
        System.out.println(func1.apply(1001,"Tom"));

        System.out.println("*******************");

        BiFunction<Integer,String,Employee> func2 = Employee :: new;
        System.out.println(func2.apply(1002,"Tom"));

    }
/*
4.数组引用格式:数组类型[] :: new
 */
    //Function<T, R>中的:R apply(T t)
    @Test
    public void test4(){
        Function<Integer,String[]> func1 = length -> new String[length];
        String[] arr1 = func1.apply(5);
        System.out.println(Arrays.toString(arr1));

        System.out.println("*******************");
        Function<Integer,String[]> func2=String[] :: new;
        String[] arr2 = func2.apply(10);
        System.out.println(Arrays.toString(arr2));
    }
}
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() {
        System.out.println("Employee().....");
    }

    public Employee(int id) {
        this.id = id;
        System.out.println("Employee(int 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;
    }
}

13.5 Stream API

public class Main {
/*
1.Stream API的理解:
    1.1 Stream关注的是对数据的运算,与CPU打交道
        集合关注的是数据的存储,与内存打交道
    1.2 java8提供了一套api,使用这套api可以对内存中的数据进行过滤、排序、映射、归约等操作,类似于sql对数据库中表的相关操作
2.注意点:
    2.1 Stream对象不会存储元素
    2.2 对Stream对象进行操作不会改变该对象,而是会返回一个新Stream对象
    2.3 对Stream对象进行的操作是延迟执行的,这意味着它们会等到需要结果的时候才执行
3.Stream的使用流程:
    3.1 实例化Stream
    3.2 一系列的中间操作
    3.3 终止操作。一旦执行终止操作,就会执行一系列的中间操作并产生结果,之后,该stream对象不能再被使用
5.示例
    5.1 步骤一:实例化Stream
        5.1.1 方式一:通过集合
 */
    @Test
    public void test1(){
        List<Employee> employees = EmployeeData.getEmployees();
        //Stream<E> stream(): 返回一个顺序流
        Stream<Employee> stream = employees.stream();
        //Stream<E> parallelStream(): 返回一个并行流
        Stream<Employee> parallelStream = employees.parallelStream();
    }
/*
        5.1.2 方式二:通过数组
 */
    @Test
    public void test2(){
        int[] arr=new int[]{1,2,3,4,5,6};
        //static <T> Stream<T> stream(T[] array): 返回一个流
        IntStream stream = Arrays.stream(arr);
        Employee e1 = new Employee(1001, "Tom");
        Employee e2 = new Employee(1002, "Jerry");
        Employee[] arr1=new Employee[]{e1,e2};
        Stream<Employee> stream1 = Arrays.stream(arr1);
    }
/*
        5.1.3 方式三:通过:static<T> Stream<T> of(T... values)
 */
    @Test
    public void test3(){
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
    }
/*
        5.1.4 方式四:创建无限流
 */
    @Test
    public void test4(){
        //static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
        //遍历前10个偶数
        Stream.iterate(0,t->t+2).limit(10).forEach(System.out::println);
        //static<T> Stream<T> generate(Supplier<T> s)
        //随机生成10个数
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
    }
/*
    5.2 步骤二:中间操作
        5.2.1 筛选与切片
 */
    @Test
    public void test5(){
        List<Employee> employees = EmployeeData.getEmployees();
        Stream<Employee> stream = employees.stream();
        //Stream<T> filter(Predicate<? super T> predicate):从流中排除某些元素
        stream.filter(e->e.getSalary()>7000).forEach(System.out::println);
        //Stream<T> limit(long maxSize):使流的元素不超过给定数量
        employees.stream().limit(3).forEach(System.out::println);
        //Stream<T> skip(long n):返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
        employees.stream().skip(3).forEach(System.out::println);
        //Stream<T> distinct():通过 hashCode() 和 equals() 去除流中的重复元素
        employees.add(new Employee(1010,"刘强东",40,8000));
        employees.add(new Employee(1010,"刘强东",40,8000));
        employees.add(new Employee(1010,"刘强东",40,8000));
        employees.add(new Employee(1010,"刘强东",40,8000));
        employees.add(new Employee(1010,"刘强东",40,8000));
        employees.add(new Employee(1010,"刘强东",40,8000));
        employees.stream().distinct().forEach(System.out::println);
    }
/*
        5.2.2 映射
 */
    @Test
    public void test6(){
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        //<R> Stream<R> map(Function<? super T, ? extends R> mapper):将流中的每个元素映射成一个新的元素
        list.stream().map(str->str.toUpperCase()).forEach(System.out::println);
        //练习一:获取员工姓名长度大于3的员工的姓名
        List<Employee> employees = EmployeeData.getEmployees();
        Stream<String> namesStream = employees.stream().map(Employee::getName);
        namesStream.filter(name->name.length()>3).forEach(System.out::println);
        //练习二:
        Stream<Stream<Character>> streamStream = list.stream().map(Main::fromStringToStream);
        streamStream.forEach(s->s.forEach(System.out::println));
        System.out.println();
        //<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper):将流中的每个元素都换成另一个流,然后把所有流连接成一个流
        Stream<Character> characterStream = list.stream().flatMap(Main::fromStringToStream);
        characterStream.forEach(System.out::println);
    }
    //将字符串中的多个字符构成的集合转换为对应的Stream的实例
    public static Stream<Character> fromStringToStream(String str){//aa
        ArrayList<Character> list = new ArrayList<>();
        for(Character c : str.toCharArray()){
            list.add(c);
        }
        return list.stream();
    }
/*
        5.2.3 排序
 */
    @Test
    public void test7(){
        List<Integer> list = Arrays.asList(12, 43, 65, 34, 87, 0, -98, 7);
        //Stream<T> sorted():自然排序
        list.stream().sorted().forEach(System.out::println);
        List<Employee> employees = EmployeeData.getEmployees();
//        employees.stream().sorted().forEach(System.out::println);//抛异常,原因:Employee没有实现Comparable接口
        //Stream<T> sorted(Comparator<? super T> comparator):定制排序
        employees.stream().sorted((e1,e2)->{
            int ageValue=Integer.compare(e1.getAge(),e2.getAge());
            if(ageValue!=0){
                return ageValue;
            }else {
                return -Double.compare(e1.getSalary(),e2.getSalary());
            }
        }).forEach(System.out::println);
    }
/*
    5.3 步骤三:终止操作
        5.3.1 匹配与查找
 */
    @Test
    public void test8(){
        List<Employee> employees = EmployeeData.getEmployees();
        //boolean allMatch(Predicate<? super T> predicate):检查是否匹配流中的所有元素
        boolean allMatch = employees.stream().allMatch(e -> e.getAge() > 18);
        //boolean anyMatch(Predicate<? super T> predicate):检查是否至少匹配流中的一个元素
        boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() > 10000);
        //boolean noneMatch(Predicate<? super T> predicate):检查是否没有匹配流中的元素
        boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startsWith("雷"));
        //Optional<T> findFirst():返回流中第一个元素
        Optional<Employee> employee = employees.stream().findFirst();
        //Optional<T> findAny():返回流中任意一个元素
        Optional<Employee> employee1 = employees.parallelStream().findAny();
        //long count():返回流中元素的总个数
        long count = employees.stream().filter(e -> e.getSalary() > 5000).count();
        //Optional<T> max(Comparator<? super T> comparator):返回流中最大值
        Stream<Double> salaryStream = employees.stream().map(e -> e.getSalary());
        Optional<Double> maxSalary = salaryStream.max(Double::compare);
        //Optional<T> min(Comparator<? super T> comparator):返回流中最小值
        Optional<Employee> employee2 = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        //void forEach(Consumer<? super T> action):内部迭代
        employees.stream().forEach(System.out::println);
        //也可以直接使用集合的遍历操作
        employees.forEach(System.out::println);
    }
/*
        5.3.2 归约
 */
    @Test
    public void test9(){
        //T reduce(T identity, BinaryOperator<T> accumulator):可以将流中元素反复结合起来,得到一个值。返回 T
        //计算1-10的自然数的和
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer sum = list.stream().reduce(10, Integer::sum);
        //Optional<T> reduce(BinaryOperator<T> accumulator):可以将流中元素反复结合起来,得到一个值。返回 Optional<T>
        //计算公司所有员工工资的总和
        List<Employee> employees = EmployeeData.getEmployees();
        Stream<Double> salaryStream = employees.stream().map(Employee::getSalary);
        Optional<Double> sumMoney = salaryStream.reduce(Double::sum);
    }
/*
        5.3.3 收集
 */
    @Test
    public void test10(){
        //<R, A> R collect(Collector<? super T, A, R> collector):将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
        //查找工资大于6000的员工,结果返回为一个List或Set
        List<Employee> employees = EmployeeData.getEmployees();
        List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());
        employeeList.forEach(System.out::println);
        System.out.println();
        Set<Employee> employeeSet = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet());
        employeeSet.forEach(System.out::println);
    }
}
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;
    }
}
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() {
        System.out.println("Employee().....");
    }

    public Employee(int id) {
        this.id = id;
        System.out.println("Employee(int 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;
    }
}

13.6 Optional类的使用

public class Main {
/*
1.理解:为解决空指针问题而生!
   1.1 Optional<T> 类是一个容器类,它内部定义了一个value属性:private final T value; 如果value为空,表示这个值不存在;如果value非空,表示这个值存在
   1.2 原来用 null 表示一个值不存在,现在Optional<T> 类可以更好地表达这个概念,并且可以避免空指针异常
2.常用方法:
 */
    @Test
    public void test1(){
        //2.1 static<T> Optional<T> empty():返回一个Optional对象,该Optional对象内部的value为null
        Optional<Object> op1 = Optional.empty();
        System.out.println(op1);//Optional.empty
        //2.2 boolean isPrent():如果Optional对象内部的value为null,则返回false;否则,返回true
        if(!op1.isPresent()){
            System.out.println("数据为空");
        }
        //2.3 T get():如果Optional对象内部的value为null,则报异常:java.util.NoSuchElementException: No value present;否则,返回Optional对象内部的value
//        System.out.println(op1.get());
    }
    //get通常与of搭配,用于获取Optional对象内部的value
    @Test
    public void test2(){
        Girl girl = new Girl();
//        girl=null;
        //2.4 static <T> Optional<T> of(T value):返回一个Optional对象,该Optional对象内部的value设为参数value,其中参数value必须非空,如果参数value为null,则报异常:java.lang.NullPointerException
        Optional<Girl> optionalGirl = Optional.of(girl);
        System.out.println(optionalGirl.get());//Girl{name='null'}
    }
    //ofNullable和orElse配合使用
    @Test
    public void test3(){
        Girl girl = new Girl();
        girl=null;
        //2.5 static <T> Optional<T> ofNullable(T value): 返回一个Optional对象,该Optional对象内部的value即为参数value,不要求参数value必须非空
        Optional<Girl> optionalGirl = Optional.ofNullable(girl);
        System.out.println(optionalGirl);//Optional.empty
        //2.6 T orElse(T other):如果Optional对象内部的value非空,则返回value;否则,返回other
        Girl girl1 = optionalGirl.orElse(new Girl("迪丽热巴"));
        System.out.println(girl1);//Girl{name='迪丽热巴'}
    }
    @Test
    public void test4(){
        Boy boy=null;
        String girlName = getGirlName2(boy);
        System.out.println(girlName);//迪丽热巴
        boy=new Boy();
        String girlName1 = getGirlName2(boy);
        System.out.println(girlName1);//古力娜扎
        boy=new Boy(new Girl("苍老师"));
        String girlName2 = getGirlName2(boy);
        System.out.println(girlName2);//苍老师

    }
    public String getGirlName(Boy boy){
        return boy.getGirl().getName();//容易报异常:java.lang.NullPointerException
    }
    //优化以后的getGirlName()
    public String getGirlName1(Boy boy){
        if(boy!=null){
            Girl girl = boy.getGirl();
            if(girl!=null){
                return girl.getName();
            }
        }
        return null;
    }
    //ofNullable和orElse配合使用的getGirlName()
    public String getGirlName2(Boy boy){
        Optional<Boy> boyOptional = Optional.ofNullable(boy);
        Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪丽热巴")));
        Girl girl = boy1.getGirl();
        Optional<Girl> girlOptional = Optional.ofNullable(girl);
        Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));
        return girl1.getName();
    }
}
class Girl {

    private String name;

    @Override
    public String toString() {
        return "Girl{" +
                "name='" + name + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Girl() {

    }

    public Girl(String name) {

        this.name = name;
    }
}
class Boy {
    private Girl girl;

    @Override
    public String toString() {
        return "Boy{" +
                "girl=" + girl +
                '}';
    }

    public Girl getGirl() {
        return girl;
    }

    public void setGirl(Girl girl) {
        this.girl = girl;
    }

    public Boy() {

    }

    public Boy(Girl girl) {

        this.girl = girl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值