day07--java高级编程:JDK8的新特性,JDK9的新特性,JDK10的新特性,JDK11的新特性,JDK15的新特性

1 JDK8的其它新特性

说明:一些8中的新特性在,java高级部分学习的同时顺便讲过了。

1.1 JDK8新特性的总体结构

在这里插入图片描述

1.2 Java 8新特性简介

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.3 Lambda表达式

1.3.1 出现背景

在这里插入图片描述

1.3.2 Lambda表达式的使用举例

package com.atguigu.java1;


import org.junit.Test;

import java.util.Comparator;

/**
 * Lambda表达式的使用举例
 *
 * @author shkstart
 * @create 2019 上午 11:30
 */
public class LambdaTest {

    @Test
    public void test1(){
        //Runnable:是多线程创建接口的一种方式
        Runnable r1 = new Runnable() { //接口的匿名实现类
            @Override
            public void run() {
                System.out.println("我爱北京天安门");
            }
        };

        r1.run();

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

        Runnable r2 = () -> System.out.println("我爱北京故宫");

        r2.run();
    }


    @Test
    public void test2(){

        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };

        int compare1 = com1.compare(12,21);
        System.out.println(compare1);

        System.out.println("***********************");
        //Lambda表达式的写法
        Comparator<Integer> com2 = (o1,o2) -> Integer.compare(o1,o2);

        int compare2 = com2.compare(32,21);
        System.out.println(compare2);


        System.out.println("***********************");
        //方法引用
        Comparator<Integer> com3 = Integer :: compare;

        int compare3 = com3.compare(32,21);
        System.out.println(compare3);
    }

}

1.3.3 Lambda表达式语法的使用

package com.atguigu.java1;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Consumer;

/**
 * Lambda表达式的使用
 *
 * 1.举例: (o1,o2) -> Integer.compare(o1,o2);
 * 2.格式:
 *      -> :lambda操作符 或 箭头操作符
 *      ->左边:lambda形参列表 (其实就是接口中的抽象方法的形参列表)
 *      ->右边:lambda体 (其实就是重写的抽象方法的方法体)
 *
 * 3. Lambda表达式的使用:(分为6种情况介绍)
 *
 *    总结:
 *    ->左边:lambda形参列表的参数类型可以省略(类型推断);如果lambda形参列表只有一个参数,其一对()也可以省略
 *    ->右边:lambda体应该使用一对{}包裹;如果lambda体只有一条执行语句(可能是return语句),省略这一对{}和return关键字
 *
 * 4.Lambda表达式的本质:作为函数式接口的实例(可以理解为接口的实现类对象)
 *  要求:接口中的抽象方法只有一个
 *
 * 5. 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。我们可以在一个接口上使用 @FunctionalInterface 注解,
 *   这样做可以检查它是否是一个函数式接口。(注意:自定义一个接口,接口里面只有一个抽象方法,这样的接口叫做函数式接口。加上这个注解是为了检查
 *       此接口是否为函数式接口,是不是函数是接口和加上此注解没有关系,注解只是起到检查的作用。)
 *
 * 6. 所以以前用匿名实现类表示的现在都可以用Lambda表达式来写。
 *
 * @author shkstart
 * @create 2019 上午 11:40
 */
public class LambdaTest1 {
    //语法格式一:无参,无返回值
    @Test
    public void test1(){
        Runnable r1 = new Runnable() {//接口的匿名实现类
            @Override
            public void run() {
                System.out.println("我爱北京天安门");
            }
        };

        r1.run();

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

        Runnable r2 = () -> {
            System.out.println("我爱北京故宫");
        };

        r2.run();
    }
    //语法格式二:Lambda 需要一个参数,但是没有返回值。
    @Test
    public void test2(){

        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        con.accept("谎言和誓言的区别是什么?");

        System.out.println("*******************");
        Consumer<String> con1 = (String s) -> {
            System.out.println(s);
        };
        con1.accept("一个是听得人当真了,一个是说的人当真了");

    }

    //语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
    //优化test2的方式:
    @Test
    public void test3(){

        Consumer<String> con1 = (String s) -> {
            System.out.println(s);
        };
        con1.accept("一个是听得人当真了,一个是说的人当真了");

        System.out.println("*******************");
        //有泛型指定类型后 ,后面的数据类型可以省略,类似于之前学的如 test4
        Consumer<String> con2 = (s) -> {
            System.out.println(s);
        };
        con2.accept("一个是听得人当真了,一个是说的人当真了");

    }

    @Test
    public void test4(){

        ArrayList<String> list = new ArrayList<>();//类型推断

        int[] arr = {1,2,3};//类型推断

    }

    //语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略
    //优化test3的方式:
    @Test
    public void test5(){
        Consumer<String> con1 = (s) -> {
            System.out.println(s);
        };
        con1.accept("一个是听得人当真了,一个是说的人当真了");

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

        Consumer<String> con2 = s -> {
            System.out.println(s);
        };
        con2.accept("一个是听得人当真了,一个是说的人当真了");


    }

    //语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
    @Test
    public void test6(){

        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println(o1);
                System.out.println(o2);
                return o1.compareTo(o2);
            }
        };

        System.out.println(com1.compare(12,21));

        System.out.println("*****************************");
        Comparator<Integer> com2 = (o1,o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };

        System.out.println(com2.compare(12,6));


    }

    //语法格式六:当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略
    @Test
    public void test7(){

        Comparator<Integer> com1 = (o1,o2) -> {
            return o1.compareTo(o2);
        };

        System.out.println(com1.compare(12,6));

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

        Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);

        System.out.println(com2.compare(12,21));

    }

    @Test
    public void test8(){
        Consumer<String> con1 = s -> {
            System.out.println(s);
        };
        con1.accept("一个是听得人当真了,一个是说的人当真了");

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

        Consumer<String> con2 = s -> System.out.println(s);

        con2.accept("一个是听得人当真了,一个是说的人当真了");

    }

}

1.4 函数式接口

1.4.1 概述

在这里插入图片描述
在这里插入图片描述

1.4.2 举例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.4.3 Java 内置四大核心函数式接口

说明:开发中见到的这几个四大核心函数式接口其它接口,在实例化时都可以使用Lambda表达式简写。
在这里插入图片描述
测试:

package com.atguigu.java1;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * java内置的4大核心函数式接口
 *
 * 消费型接口 Consumer<T>     void accept(T t)
 * 供给型接口 Supplier<T>     T get()
 * 函数型接口 Function<T,R>   R apply(T t)
 * 断定型接口 Predicate<T>    boolean test(T t)
 * 说明:凡是以前定义过的接口都属性这4种形式,那么就没有必要在进行定义了 直接使用内置的接口即可。
 *
 * @author shkstart
 * @create 2019 下午 2:29
 */
public class LambdaTest2 {
    //消费型接口测试:
    @Test
    public void test1(){
        //原来写法
        happyTime(500, new Consumer<Double>() {
            @Override
            public void accept(Double aDouble) {
                System.out.println("学习太累了,去天上人间买了瓶矿泉水,价格为:" + aDouble);
            }
        });

        System.out.println("********************");
        //Lambda表达式的写法    这里写aDouble也一样  流程是:在test1()中调用happyTime方法并赋值,而在happyTime中进行回调函数 把值赋给accept().
        happyTime(400,money -> System.out.println("学习太累了,去天上人间喝了口水,价格为:" + money));
    }

    public void happyTime(double money, Consumer<Double> con){
        con.accept(money);
    }

	//断定型接口
    @Test
    public void test2(){
        List<String> list = Arrays.asList("北京","南京","天津","东京","西京","普京");

        List<String> filterStrs = filterString(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("京");
            }
        });

        System.out.println(filterStrs);


        List<String> filterStrs1 = filterString(list,s -> s.contains("京"));
        System.out.println(filterStrs1);
    }

    //根据给定的规则,过滤集合中的字符串。此规则由Predicate的方法决定
    public List<String> filterString(List<String> list, Predicate<String> pre){

        ArrayList<String> filterList = new ArrayList<>();

        for(String s : list){
            if(pre.test(s)){
                filterList.add(s);
            }
        }

        return filterList;

    }

}

1.4.4 Java 其他接口

在这里插入图片描述

1.5 方法引用与构造器引用

1.5.1 方法引用概述

在这里插入图片描述

1.5.2 构造器引用和数组引用

在这里插入图片描述
在这里插入图片描述

1.5.3 综合测试

Employee类:

package com.atguigu.java2;

/**
 * @author shkstart 邮箱:shkstart@126.com
 */
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() {
		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;
	}
}

EmployeeData类:

package com.atguigu.java2;

import java.util.ArrayList;
import java.util.List;
/**
 * 提供用于测试的数据
 * 
 * @author shkstart 邮箱:shkstart@126.com
 *
 */
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;
	}
	
}

MethodRefTest类:

package com.atguigu.java2;

import org.junit.Test;

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 方法引用的使用
 *
 * 1.使用情境:当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
 *
 * 2.方法引用,本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例。所以
 *   方法引用,也是函数式接口的实例。    Lambda表达式的进一步简化。
 *
 * 3. 使用格式:  类(或对象) :: 方法名
 *
 * 4. 具体分为如下的三种情况:
 *    情况1     对象 :: 非静态方法()
 *    情况2     类 :: 静态方法
 *
 *    情况3     类 :: 非静态方法
 *
 * 5. 方法引用使用的要求:要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的
 *    形参列表和返回值类型相同!(针对于情况1和情况2)
 *
 * Created by shkstart.
 */
public class MethodRefTest {

	// 情况一:对象 :: 实例方法
	//Consumer中的void accept(T t)
	//PrintStream中的void println(T t)
	//解释:Consumer接口中的方法accept和PrintStream类中的println方法进行比较,发现2个方法的形参列表和返回值类型相同 并且accept方法
	//    本质上想要做的事情就是System.out.println(str)  ,System.out.println(str)在accept方法中使用了并且返回值和参数类型相同,
	//    就可以简写为方法的引用。
	@Test
	public void test1() {
		Consumer<String> con1 = str -> System.out.println(str);
		con1.accept("北京");

		System.out.println("*******************");
		PrintStream ps = System.out;
		Consumer<String> con2 = ps::println;
		con2.accept("beijing");
	}
	
	//Supplier中的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中的int compare(T t1,T t2)
	//Integer中的int compare(T t1,T t2)
	@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,3));

	}
	
	//Function中的R apply(T t)
	//Math中的Long round(Double d)
	@Test
	public void test4() {
		Function<Double,Long> func = new Function<Double, Long>() {
			@Override
			public Long apply(Double d) {
				return Math.round(d);
			}
		};

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

		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.6));
	}

	// 情况三:类 :: 实例方法  (有难度)
	// Comparator中的int comapre(T t1,T t2)
	// String中的int t1.compareTo(t2)
	@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("abd","abm"));
	}

	//BiPredicate中的boolean test(T t1, T t2);
	//String中的boolean t1.equals(t2)
	@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中的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));


	}

}

ConstructorRefTest类:

package com.atguigu.java2;

import org.junit.Test;

import java.util.Arrays;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 一、构造器引用
 *      和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致。
 *      抽象方法的返回值类型即为构造器所属的类的类型
 *
 * 二、数组引用
 *     大家可以把数组看做是一个特殊的类,则写法与构造器引用一致。
 *
 * Created by shkstart
 */
public class ConstructorRefTest {
	//构造器引用
    //Supplier中的T get()
    //Employee的空参构造器:Employee()
    @Test
    public void test1(){
        //面向对象写法:
        Supplier<Employee> sup = new Supplier<Employee>() {
            @Override
            public Employee get() {
                return new Employee();
            }
        };
        System.out.println("*******************");
        //Lambda表达式写法:
        Supplier<Employee>  sup1 = () -> new Employee();
        System.out.println(sup1.get());

        System.out.println("*******************");
        //方法引用写法:
        Supplier<Employee>  sup2 = Employee :: new;
        System.out.println(sup2.get());
    }

	//Function中的R apply(T t)
    @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中的R apply(T t,U u)
    @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"));

    }

	//数组引用
    //Function中的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));

    }
}


1.6 强大的Stream API

1.6.1 概述

在这里插入图片描述

1.6.2 出现背景

在这里插入图片描述

1.6.3 什么是 Stream

在这里插入图片描述

1.6.4 Stream 的操作三个步骤

在这里插入图片描述

1.6.5 Stream的四种实例化方式(步骤一)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
测试·:
EmployeeData:

package com.atguigu.java2;

import java.util.ArrayList;
import java.util.List;
/**
 * 提供用于测试的数据
 * 
 * @author shkstart 邮箱:shkstart@126.com
 *
 */
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;
	}
	
}

StreamAPITest类:

package com.atguigu.java3;

import com.atguigu.java2.Employee;
import com.atguigu.java2.EmployeeData;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 1. Stream关注的是对数据的运算,与CPU打交道
 *    集合关注的是数据的存储,与内存打交道
 *
 * 2.
 * ①Stream 自己不会存储元素。
 * ②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
 * ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
 *
 * 3.Stream 执行流程
 * ① Stream的实例化(四种方式创建对象)
 * ② 一系列的中间操作(过滤、映射、...)
 * ③ 终止操作
 *
 * 4.说明:
 * 4.1 一个中间操作链,对数据源的数据进行处理
 * 4.2 一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
 *
 *
 *  测试Stream的实例化
 *
 * @author shkstart
 * @create 2019 下午 4:25
 */
public class StreamAPITest {

    //创建 Stream方式一:通过集合
    @Test
    public void test1(){
        List<Employee> employees = EmployeeData.getEmployees();

//        default Stream<E> stream() : 返回一个顺序流  (顺序流:在执行中间操作时,按照集合中数据添加的顺序取数据)
        Stream<Employee> stream = employees.stream();

//        default Stream<E> parallelStream() : 返回一个并行流 (并行流:在执行中间操作时,类似于多个线程同时取数据,不一定按照数据添加的顺序取数据)
        Stream<Employee> parallelStream = employees.parallelStream();

    }

    //创建 Stream方式二:通过数组
    @Test
    public void test2(){
        //stream的类型: 如果放的是int类型的数组则是 IntStream
        int[] arr = new int[]{1,2,3,4,5,6};
        //调用Arrays类的static <T> Stream<T> stream(T[] array): 返回一个流
        IntStream stream = Arrays.stream(arr);
        //自定义类的数组stream的类型 :通过泛型体现
        Employee e1 = new Employee(1001,"Tom");
        Employee e2 = new Employee(1002,"Jerry");
        Employee[] arr1 = new Employee[]{e1,e2};
        Stream<Employee> stream1 = Arrays.stream(arr1);

    }
    //创建 Stream方式三:通过Stream的of()
    @Test
    public void test3(){

        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);//认为里面的数据是引用类型  包装类

    }

    //创建 Stream方式四:创建无限流
    @Test
    public void test4(){

//      迭代
//      public 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);


//      生成
//      public static<T> Stream<T> generate(Supplier<T> s)
        Stream.generate(Math::random).limit(10).forEach(System.out::println);

    }

}

1.6.6 Stream的中间操作(步骤二)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
测试:
EmployeeData类:

package com.atguigu.java2;

import java.util.ArrayList;
import java.util.List;
/**
 * 提供用于测试的数据
 * 
 * @author shkstart 邮箱:shkstart@126.com
 *
 */
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;
	}
	
}

StreamAPITest1类:

package com.atguigu.java3;

import com.atguigu.java2.Employee;
import com.atguigu.java2.EmployeeData;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * 测试Stream的中间操作
 *
 * @author shkstart
 * @create 2019 下午 4:42
 */
public class StreamAPITest1 {

    //1-筛选与切片
    @Test
    public void test1(){
        List<Employee> list = EmployeeData.getEmployees();
//        filter(Predicate p)——接收 Lambda , 从流中排除某些元素。
        Stream<Employee> stream = list.stream();
        //练习:查询员工表中薪资大于7000的员工信息
        stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);

        System.out.println();
//        limit(n)——截断流,使其元素不超过给定数量。
        list.stream().limit(3).forEach(System.out::println);
        System.out.println();

//        skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
        list.stream().skip(3).forEach(System.out::println);

        System.out.println();
//        distinct()——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素

        list.add(new Employee(1010,"刘强东",40,8000));
        list.add(new Employee(1010,"刘强东",41,8000));
        list.add(new Employee(1010,"刘强东",40,8000));
        list.add(new Employee(1010,"刘强东",40,8000));
        list.add(new Employee(1010,"刘强东",40,8000));

//        System.out.println(list);

        list.stream().distinct().forEach(System.out::println);
    }

    //映射
    @Test
    public void test2(){
//        map(Function f)——接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上,并将其映射成一个新的元素。
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);

//        练习1:获取员工姓名长度大于3的员工的姓名。
        List<Employee> employees = EmployeeData.getEmployees();
        Stream<String> namesStream = employees.stream().map(Employee::getName);
        namesStream.filter(name -> name.length() > 3).forEach(System.out::println);
        System.out.println();
        //练习2:
        Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest1::fromStringToStream);
        streamStream.forEach(s ->{
            s.forEach(System.out::println);
        });
        System.out.println();
//        flatMap(Function f)——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
        Stream<Character> characterStream = list.stream().flatMap(StreamAPITest1::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();

    }



    @Test
    public void test3(){
        ArrayList list1 = new ArrayList();
        list1.add(1);
        list1.add(2);
        list1.add(3);

        ArrayList list2 = new ArrayList();
        list2.add(4);
        list2.add(5);
        list2.add(6);

//        list1.add(list2);
        list1.addAll(list2);
        System.out.println(list1);

    }

    //3-排序
    @Test
    public void test4(){
//        sorted()——自然排序
        List<Integer> list = Arrays.asList(12, 43, 65, 34, 87, 0, -98, 7);
        list.stream().sorted().forEach(System.out::println);
        //抛异常,原因:Employee没有实现Comparable接口
//        List<Employee> employees = EmployeeData.getEmployees();
//        employees.stream().sorted().forEach(System.out::println);


//        sorted(Comparator com)——定制排序

        List<Employee> employees = EmployeeData.getEmployees();
        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);
    }

}

1.6.7 Stream 的终止操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
测试:
EmployeeData类:

package com.atguigu.java2;

import java.util.ArrayList;
import java.util.List;
/**
 * 提供用于测试的数据
 * 
 * @author shkstart 邮箱:shkstart@126.com
 *
 */
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;
	}
	
}

StreamAPITest2类:

package com.atguigu.java3;

import com.atguigu.java2.Employee;
import com.atguigu.java2.EmployeeData;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 测试Stream的终止操作
 *
 * @author shkstart
 * @create 2019 下午 6:37
 */
public class StreamAPITest2 {

    //1-匹配与查找
    @Test
    public void test1(){
        List<Employee> employees = EmployeeData.getEmployees();

//        allMatch(Predicate p)——检查是否匹配所有元素。
//          练习:是否所有的员工的年龄都大于18
        boolean allMatch = employees.stream().allMatch(e -> e.getAge() > 18);
        System.out.println(allMatch);

//        anyMatch(Predicate p)——检查是否至少匹配一个元素。
//         练习:是否存在员工的工资大于 10000
        boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() > 10000);
        System.out.println(anyMatch);

//        noneMatch(Predicate p)——检查是否没有匹配的元素。
//          练习:是否存在员工姓“雷”
        boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startsWith("雷"));
        System.out.println(noneMatch);
//        findFirst——返回第一个元素
        Optional<Employee> employee = employees.stream().findFirst();
        System.out.println(employee);
//        findAny——返回当前流中的任意元素
        Optional<Employee> employee1 = employees.parallelStream().findAny();
        System.out.println(employee1);

    }

    @Test
    public void test2(){
        List<Employee> employees = EmployeeData.getEmployees();
        // count——返回流中元素的总个数
        long count = employees.stream().filter(e -> e.getSalary() > 5000).count();
        System.out.println(count);
//        max(Comparator c)——返回流中最大值
//        练习:返回最高的工资:
        Stream<Double> salaryStream = employees.stream().map(e -> e.getSalary());
        Optional<Double> maxSalary = salaryStream.max(Double::compare);
        System.out.println(maxSalary);
//        min(Comparator c)——返回流中最小值
//        练习:返回最低工资的员工
        Optional<Employee> employee = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(employee);
        System.out.println();
//        forEach(Consumer c)——内部迭代
        employees.stream().forEach(System.out::println);

        //使用集合的遍历操作
        employees.forEach(System.out::println);
    }

    //2-归约
    @Test
    public void test3(){
//        reduce(T identity, BinaryOperator)——可以将流中元素反复结合起来,得到一个值。返回 T
//        练习1:计算1-10的自然数的和
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer sum = list.stream().reduce(0, Integer::sum);
        System.out.println(sum);


//        reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。返回 Optional<T>
//        练习2:计算公司所有员工工资的总和
        List<Employee> employees = EmployeeData.getEmployees();
        Stream<Double> salaryStream = employees.stream().map(Employee::getSalary);
//        Optional<Double> sumMoney = salaryStream.reduce(Double::sum);
        Optional<Double> sumMoney = salaryStream.reduce((d1,d2) -> d1 + d2);
        System.out.println(sumMoney.get());

    }

    //3-收集
    @Test
    public void test4(){
//        collect(Collector c)——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
//        练习1:查找工资大于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);




    }
}

1.7 Optional 类

1.7.1 概述

在这里插入图片描述

1.7.2 常用方法

在这里插入图片描述

1.7.3 测试

Boy类:

package com.atguigu.java4;

/**
 * @author shkstart
 * @create 2019 下午 7:22
 */
public 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;
    }
}

Girl类:

package com.atguigu.java4;

/**
 * @author shkstart
 * @create 2019 下午 7:23
 */
public 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;
    }
}

OptionalTest类:

package com.atguigu.java4;

import org.junit.Test;

import java.util.Optional;

/**
 * Optional类:为了在程序中避免出现空指针异常而创建的。
 *
 * 常用的方法:ofNullable(T t)
 *            orElse(T t)
 *
 * @author shkstart
 * @create 2019 下午 7:24
 */
public class OptionalTest {

    /*
    Optional.of(T t) : 创建一个 Optional 实例,t必须非空;
    Optional.empty() : 创建一个空的 Optional 实例
    Optional.ofNullable(T t):t可以为null

     */
    @Test
    public void test1(){
        Girl girl = new Girl();
//        girl = null;
        //of(T t):保证t是非空的
        Optional<Girl> optionalGirl = Optional.of(girl);

    }

    @Test
    public void test2(){
        Girl girl = new Girl();
//        girl = null;
        //ofNullable(T t):t可以为null
        Optional<Girl> optionalGirl = Optional.ofNullable(girl);
        System.out.println(optionalGirl);
        //orElse(T t1):如果单前的Optional内部封装的t是非空的,则返回内部的t.
        //如果内部的t是空的,则返回orElse()方法中的参数t1.
        Girl girl1 = optionalGirl.orElse(new Girl("赵丽颖"));
        System.out.println(girl1);

    }


    public String getGirlName(Boy boy){
        return boy.getGirl().getName();
    }

    @Test
    public void test3(){
        Boy boy = new Boy();
        boy = null;
        String girlName = getGirlName(boy);
        System.out.println(girlName);

    }
    //优化以后的getGirlName():
    public String getGirlName1(Boy boy){
        if(boy != null){
            Girl girl = boy.getGirl();
            if(girl != null){
                return girl.getName();
            }
        }

        return null;

    }

    @Test
    public void test4(){
        Boy boy = new Boy();
        boy = null;
        String girlName = getGirlName1(boy);
        System.out.println(girlName);

    }

    //使用Optional类的getGirlName():
    public String getGirlName2(Boy boy){

        Optional<Boy> boyOptional = Optional.ofNullable(boy);
        //此时的boy1一定非空
        Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪丽热巴")));

        Girl girl = boy1.getGirl();

        Optional<Girl> girlOptional = Optional.ofNullable(girl);
        //girl1一定非空
        Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));

        return girl1.getName();
    }

    @Test
    public void test5(){
        Boy boy = null;
        boy = new Boy();
        boy = new Boy(new Girl("苍老师"));
        String girlName = getGirlName2(boy);
        System.out.println(girlName);

    }



}

2JDK9的新特性

注意:需要下载安装新版本的JDK才能使用这些新特性。

2.1 概述

在这里插入图片描述

3 JDK10的新特性

4 JDK11的新特性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/28760.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AntDB 企业增强特性介绍——AntDB在线数据扩容关键技术

数据库集群安装完成后&#xff0c;其数据存储容量是预先规划并确定的。随着时间的推移以及业务量的增加&#xff0c;数据库集群中的可用存储空间不断减少&#xff0c;面临数据存储容量扩充的需求。 传统的在线扩容的流程大致如下。 &#xff08;1&#xff09;在集群中加入新的 …

数据库迁移 | Oracle数据迁移方案之技术两三点

今年Oracle似乎又火了&#xff0c;火得要下掉&#xff0c;目前中国大概有240数据库企业&#xff0c;在国产信创的大趋势下&#xff0c;一片欣欣向荣&#xff0c;国库之春已然来临。到今天为止&#xff0c;Oracle依旧是市场份额最大的数据库&#xff0c;天下苦秦久矣&#xff0c…

【JVM 监控工具】JVisualVM的使用

文章目录 前言二、启动JVisualVM三、安装插件四、使用 前言 JVisualVM是一个Java虚拟机的监控工具&#xff0c;要是需要对JVM的性能进行监控可以使用这个工具哦 使用这个工具&#xff0c;你就可以监控到java虚拟机的gc过程了 那么&#xff0c;这么强大的工具怎么下载呢&…

顶奢好文:3W字,穿透Spring事务原理、源码,至少读10遍

说在前面 在40岁老架构师 尼恩的读者社区(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、美团、极兔、有赞、希音的面试资格&#xff0c;Spring事务源码的面试题&#xff0c;经常遇到&#xff1a; (1) spring什么情况下进行事务回滚&#xff1f; (2) spring 事务…

Transformer在CV领域有可能替代CNN吗?

目前已经有基于Transformer在三大图像问题上的应用&#xff1a;分类&#xff08;ViT&#xff09;&#xff0c;检测&#xff08;DETR&#xff09;和分割&#xff08;SETR&#xff09;&#xff0c;并且都取得了不错的效果。那么未来&#xff0c;Transformer有可能替换CNN吗&#…

索尼RSV视频修复方法论视频文件修复时样本文件的三同

索尼RSV类的文件修复案例有很多&#xff0c;程序操作也很简单没什么可说的&#xff0c;这次这个索尼ILCE-7SM3的案例就是为了让大家更好的认识视频修复中我称之为“三同“的重要性&#xff0c;想要恢复的效果好必须要把准备工作做到位。 故障文件:45.1G RSV文件 故障现象: 索…

工具篇--4 消息中间件-RabbitMq 模型介绍

1 介绍: RabbitMQ 是一个开源的消息中间件&#xff0c;它实现了 AMQP&#xff08;高级消息队列协议&#xff09;标准&#xff0c;并且支持多种语言和操作系统&#xff0c;包括 Java、Python、Ruby、PHP、.NET、MacOS、Windows、Linux 等等。RabbitMQ 提供了可靠的消息传递机制…

竞赛无人机搭积木式编程(三)---用户自定义航点自动飞行功能(全局定位,指哪打哪)

竞赛无人机搭积木式编程&#xff08;三&#xff09;---用户自定义航点自动飞行功能&#xff08;全局定位&#xff0c;指哪打哪&#xff09; 无名小哥 2023年6月10日 用户通过对前面两讲中全国大学生电子设计竞赛真题植保无人机&#xff08;2021&#xff09;、送货无人机&#…

【UE 从零开始制作坦克】2-控制坦克移动(简单的移动效果)

效果 步骤 1. 新建蓝图类&#xff0c;父类选择“VehicleWheel&#xff08;载具车轮&#xff09;” 这里就命名为“TankWheel” 双击打开“TankWheel”&#xff0c;设置形状半径为40 2. 打开 “BP_West_Tank_M1A1Abrams” 选中“网格体&#xff08;VehicleMesh&#xff09;&…

JMeter参数化4种实现方式

目录 前言&#xff1a; 1 参数化释义 2 参数化实现 CSV实例 注意事项 前言&#xff1a; 在使用JMeter进行测试时&#xff0c;参数化允许您模拟不同的用户、不同的数据、不同的操作等&#xff0c;从而增加了测试的灵活性和复用性 1 参数化释义 什么是参数化&#xff1f;…

设计模式(十八):行为型之观察者模式

设计模式系列文章 设计模式(一)&#xff1a;创建型之单例模式 设计模式(二、三)&#xff1a;创建型之工厂方法和抽象工厂模式 设计模式(四)&#xff1a;创建型之原型模式 设计模式(五)&#xff1a;创建型之建造者模式 设计模式(六)&#xff1a;结构型之代理模式 设计模式…

分布式数据库HBase

大数据基础-分布式数据库HBase 概述HBase简介HBase与传统关系数据库的对比分析 HBase数据模型数据模型概述数据模型相关概念数据坐标 HBase的实现原理HBase功能组件表和RegionRegion的定位HBase框架结构HMasterRegionServerHBase协作组件RegionColumnFamilyKeyValue小结 HBase运…

STM32单片机(六)TIM定时器 -> 第二节:TIM定时中断练习(定时器定时中断和定时器外部时钟)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

docker数据管理---数据卷,数据卷容器

在Docker中&#xff0c;数据卷&#xff08;data volumes&#xff09;和数据卷容器&#xff08;data volume containers&#xff09;是用于在容器之间共享和持久化数据的两种不同的机制。 一、数据卷 数据卷是一个特殊的目录或目录&#xff0c;可以绕过容器文件系统的常规层&a…

【RabbitMQ教程】第六章 —— RabbitMQ - 延迟队列

&#x1f4a7; 【 R a b b i t M Q 教程】第六章—— R a b b i t M Q − 延迟队列 \color{#FF1493}{【RabbitMQ教程】第六章 —— RabbitMQ - 延迟队列} 【RabbitMQ教程】第六章——RabbitMQ−延迟队列&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人…

2023年前端面试高频考点HTML5+CSS3

目录 浏览器的渲染过程⭐⭐⭐ CSS 、JS 阻塞 DOM 解析和渲染 回流&#xff08;重排&#xff09;和重绘⭐⭐ 选择器 ID选择器、类选择器、标签选择器&#xff08;按优先级高到低排序&#xff09;⭐⭐ 特殊符号选择器&#xff08;&#xff1e;,,~&#xff0c;空格&#xff0…

Stopwatch工具类计时器探究

搬砖的我们 特别是Java开发的童鞋们, 经常需要通过记录开始时间和结束时间&#xff0c;然后通过计算差值&#xff0c;得到时间差&#xff0c;如下面的代码&#xff1a; long start System.currentTimeMillis(); long end System.currentTimeMillis(); System.out.println(…

医疗设备都在用哪些晶振?

医疗设备是指用于医疗诊断、治疗、监测等方面的各种设备。随着科技的不断发展&#xff0c;医疗设备的功能不断增强&#xff0c;精度和稳定性也得到了大幅提升。在这些医疗设备中&#xff0c;晶振是非常重要的元件之一。本文将介绍医疗设备中常用的晶振类型及其特点。 一、晶振…

P20[6-8]编码器接口测速(软)

与外部中断编码器逻辑不同,此处编码器使用的是定时器方法 1.Encoder编码器部分: #include "stm32f10x.h" // Device header void Encoder_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCm…

阿里云弹性公网EIP收费价格表

阿里云弹性公网EIP怎么收费&#xff1f;EIP地域不同价格不同&#xff0c;EIP计费模式分为包年包月和按量付费&#xff0c;弹性公网IP可以按带宽收费也可以按使用流量收费&#xff0c;阿里云百科分享阿里云弹性公网IP不同地域、不同计费模式、按带宽和按使用流量详细收费价格表&…