JDK8新特性

JDK8新特性

一、Lambda表达式:

Lambda表达式:

​ 1、特殊的匿名内部类,语法更简介;

​ 2、Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递;

Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分

​ 1、左侧:(参数1,参数2·····)表示参数列表

​ 2、右侧:{}内部是方法体

~注意事项:

​ ~形参列表的数据类型会自动推断

​ ~如果形参列表为空,只需保留()

​ ~如果形参只有一个,()可以省略,只需要参数的名称即可

​ ~如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句

Typora

二、函数式接口:

  • 如果一个接口只有一个抽象方法,则该接口称为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上。

  • @Functionallnterface注解检测接口是否符合函数式接口

    /**
     * Lambda表达式的使用
     */
    public class Demo1 {
        public static void main(String[] args) {
            //匿名内部类
            Usb usb = new Usb() {
                @Override
                public void service() {
                    System.out.println("鼠标开始工作了~~~~~~~~~~");
                }
            };
    
            //Lambda表达式
            run(() -> System.out.println("鼠标开始工作了~~~~~~~~~~"););
        }
    
        public static void run(Usb usb) {
            usb.service();
        }
    }
    
    /**
     * 函数时接口
     */
    @FunctionalInterface
    interface Usb {
        void service();
    }
    

三、函数式接口使用:

Consumer消费型接口

Supplier供给型接口

Function函数型接口

predicate断言型接口

/**
 * Lambda表达式的使用
 */
public class Demo1 {
    public static void main(String[] args) {
        //匿名内部类
        Consumer<Double> consumer = new Consumer() {
            @Override
            public void accept(Object o) {
                System.out.println("今晚李公子消费" + o);
            }
        };
        happy(consumer, 1000.0);

        //Lambda表达式(消费型接口)
        happy(d -> System.out.println("今晚李公子消费" + d), 2000.0);

        //Lambda表达式(供给型接口)
        System.out.println(Arrays.toString(getNums(() -> new Random().nextInt(100), 5)));

        //Lambda表达式(函数型接口)
        System.out.println(handerString(a -> a.trim().toUpperCase(), "  abc  "));

        //Lambda表达式(断言型接口)
        List<String> list = new ArrayList(){{
            add("张三");
            add("李四");
            add("王五");
            add("张九");
        }};
        System.out.println(filterName(str -> str.startsWith("张"), list));

    }

    //Consumer消费型接口
    public static void happy(Consumer<Double> consumer, Double money) {
        consumer.accept(money);
    }

    //Supplier供给型接口
    public static int[] getNums(Supplier<Integer> supplier, int count) {
        int[] arr = new int[count];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = supplier.get();
        }
        return arr;
    }

    //Function函数型接口
    public static String handerString(Function<String, String> function, String str) {
        return function.apply(str);
    }

    //predicate断言型接口
    public static List<String> filterName(Predicate<String> predicate, List<String> list){
        List<String> resultList = new ArrayList<>();
        for(String str : list){
            if(predicate.test(str)){
                resultList.add(str);
            }
        }
        return resultList;
    }


}

四、方法引用

​ 方法引用是lambda表达式的一种简写形式。如果lambda表达式方法体中只有是调用一个特定的已经存在的方法,则可以使用方法引用

​ 常见形式:

​ 对象::实例方法

​ 类::静态方法

​ 类::实例方法

​ 类::new

五、方法引用使用

/**
 * Lambda表达式的使用
 */
public class Demo1 {
    public static void main(String[] args) {
        Consumer<String> consumer = s -> System.out.println(s);
        //1、对象::实例方法
        Consumer<String> consumer1 = System.out::print;
        consumer1.accept("你好");

        /////////////////////////////////////////////////////////////////////////

        Comparator<Integer> comparator =(o1, o2) -> Integer.compare(o1, o2);
        //2、类::静态方法
        Comparator<Integer> comparator1 = Integer::compare;
        System.out.println(comparator1.compare(2, 1));

        /////////////////////////////////////////////////////////////////////////

        Function<Employee, String> function = e -> e.getName();
        //3、类::实例方法
        Function<Employee, String> function1 = Employee::getName;
        System.out.println(function.apply(new Employee("张三", 10.0)));

        /////////////////////////////////////////////////////////////////////////

        //4、类::new
        Supplier<Employee> supplier = () -> new Employee("李四",18);
        Supplier<Employee> supplier1 = Employee::new;
        System.out.println(supplier1);
    }
}

class Employee{
    private String name;
    private double money;

    public Employee(String name, double money) {
        this.name = name;
        this.money = money;
    }

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

    public Employee() {

    }

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

    public void setMoney(double money) {
        this.money = money;
    }

    public String getName() {
        return name;
    }

    public double getMoney() {
        return money;
    }
}

六、Steram API

1、什么是Steram

流(Stream)中保存对集合或数组数据的操作。和集合类似,但集合中保存的是数据。

2、Stream特点

Stream自己不会存储元素

Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream

Stream操作时延时的。这意味着他们会等到需要结果的时候才执行

3、Stream使用步骤

创建

​ 新建一个流

中间操作

​ 在一个或多个步骤中,将初始化Stream转化到另一个Stream的中间操作

终止操作

​ 使用一个终止操作来产生一个结果。该操作会强制它之前的延迟操作立即执行。在这之后,该Stream就不能使用

4、创建Stream

通过Collection对象的stream()或parallelStream()方法

通过Arrays类的stream()方法

通过Stream接口的of(),iterate(),generate()方法

通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法

/**
 * Lambda表达式的使用
 */
public class Demo1 {
    public static void main(String[] args) {
        //1、通过Collection对象的stream()或parallelStream()方法
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("huawei");
        list.add("xiaomi");
//        Stream<String> stream = list.stream();    //串行流
        Stream<String> stringStream = list.parallelStream();    //并行流
        //遍历
//        stream.forEach(s -> System.out.println(s));
        stringStream.forEach(System.out::println);

//////////////////////////////////////////////////////////////////////////

        //2、通过Arrays类的stream()方法
        String[] arr = {"aaa","bbb","ccc","ddd"};
        Stream<String> s = Arrays.stream(arr);
        s.forEach(System.out::println);

//////////////////////////////////////////////////////////////////////////

        //3、通过Stream接口的of(),iterate(),generate()方法
        Stream<Integer> stream = Stream.of(10, 20, 30, 40, 50, 60);
        stream.forEach(System.out::println);

        //迭代流
        System.out.print("--------------生成流---------------");
        Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
        iterate.limit(10).forEach(System.out::println);

        //生成流
        System.out.print("--------------生成流---------------");
        Stream<Integer> generate = Stream.generate(() -> new Random().nextInt(100));
        generate.limit(10).forEach(System.out::println);


//////////////////////////////////////////////////////////////////////////

        //4、通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法
        System.out.print("--------------IntStream通过of---------------");
        IntStream intStream = IntStream.of(100, 200, 300, 400);
        intStream.forEach(System.out::println);

        System.out.print("--------------IntStream通过range---------------");
        IntStream range = IntStream.range(0, 10);
        range.forEach((System.out::println));

        System.out.print("--------------IntStream通过rangeClosed---------------");
        IntStream rangeClosed = IntStream.rangeClosed(0, 10);
        rangeClosed.forEach((System.out::println));
    }
}

5、中间操作、终止操作

中间操作

filter、limit、skip、distinct、sorted

map

parallel

public class Demo1 {
    public static void main(String[] args) {
        List<Employee> list = new ArrayList<>();
        list.add(new Employee("小王", 100));
        list.add(new Employee("小张", 200));
        list.add(new Employee("小李", 300));
        list.add(new Employee("小孙", 400));
        list.add(new Employee("小刘", 500));
        list.add(new Employee("小王", 100));

        //中间操作1
        //1、filter 过滤
        System.out.println("--------------filter 过滤-------------");
        list.stream().filter(e -> e.getMoney() > 200).forEach(System.out::println);

        //2、limit 限制
        System.out.println("--------------limit 限制-------------");
        list.stream().limit(2).forEach(System.out::println);

        //3、skip 跳过
        System.out.println("--------------skip 跳过-------------");
        list.stream().skip(1).forEach(System.out::println);

        //4、distinct 去重
        System.out.println("--------------distinct 去重-------------");
        list.stream().distinct().forEach(System.out::println);

        //5、sorted 排序
        System.out.println("--------------sorted 排序-------------");
        list.stream().sorted((e1, e2) -> Integer.compare(e1.getMoney(), e2.getMoney())).forEach(System.out::println);

        ////////////////////////////////////////////////////////////////////////////////

        //中间操作2
        list.stream().map(e -> e.getName()).forEach(System.out::println);

        ///////////////////////////////////////////////////////////////////////////////

        //中间操作3 采用paraller多线程效率高
        List<String> integers = new ArrayList<>();
        for (int i = 0; i < 5000000; i++) {
            integers.add(UUID.randomUUID().toString());
        }
        //串行
        long start = System.currentTimeMillis();
        long count = integers.stream().sorted().count(); //串行
//      long count = integers.parallelStream().sorted().count();//并行
        System.out.print(count);
        long end = System.currentTimeMillis();
        System.out.println("串行用时:"+(end-start));

    }
}

class Employee {
    private String name;
    private Integer money;

    public Employee(String name, Integer money) {
        this.name = name;
        this.money = money;
    }

    public Employee() {
    }

    public String getName() {
        return name;
    }

    public Integer getMoney() {
        return money;
    }

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

    public void setMoney(Integer money) {
        this.money = money;
    }

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

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

    @Override
    public int hashCode() {
        return Objects.hash(name, money);
    }
}
终止操作

forEach、min、max、count

reduce、collect

public class Demo1 {
    public static void main(String[] args) {
        List<Employee> list = new ArrayList<>();
        list.add(new Employee("小王", 100));
        list.add(new Employee("小张", 200));
        list.add(new Employee("小李", 300));
        list.add(new Employee("小孙", 400));
        list.add(new Employee("小刘", 500));
        list.add(new Employee("小王", 100));

        //终止操作foreach
        list.stream().filter(e -> {
            System.out.println("过滤了");
           return e.getMoney()>100;
        });
//                .forEach(System.out::println);

        ////////////////////////////////////////////////

        //终止操作reduce
        Optional<Integer> reduce = list.stream().map(e -> e.getMoney()).reduce((x, y) -> x + y);
        System.out.print(reduce);

        //终止操作collect,将所有员工姓名封装成一个list
       list.stream().map(e -> e.getName()).collect(Collectors.toList()).forEach(System.out::println);
    }
}

class Employee {
    private String name;
    private Integer money;

    public Employee(String name, Integer money) {
        this.name = name;
        this.money = money;
    }

    public Employee() {
    }

    public String getName() {
        return name;
    }

    public Integer getMoney() {
        return money;
    }

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

    public void setMoney(Integer money) {
        this.money = money;
    }

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

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

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

七、新时间API

1、以往时间API存在问题:

线程安全问题、设计混乱
public class Demo1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //SimpleDateFormat线程不安全
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        //创建线程池
        ExecutorService pool = Executors.newFixedThreadPool(10);
        //SimpleDateFormat线程不安全需要同步代码块
        Callable<Date> objectCallable = () -> {
            synchronized (sdf) {
                return sdf.parse("2020-04-25");
            }
        };
        List<Future<Date>> list = new ArrayList<>();
        //开启十个线程
        for (int i = 0; i < 10; i++) {
            Future<Date> submit = pool.submit(objectCallable);
            list.add(submit);
        }
        //打印结果
        for (Future<Date> future : list) {
            System.out.println(future.get());
        }
        pool.shutdown();

        /////////////////////////////////////////////////////////////////////
        
        //新时间API:DateTimeFormatter、LocalDate线程安全
        pool = Executors.newFixedThreadPool(10);
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        //SimpleDateFormat线程不需要需要同步代码块
        Callable<LocalDate> localDateCallable = () -> LocalDate.parse("2020-04-25",dtf);
        List<Future<LocalDate>> list1 = new ArrayList<>();
        //开启十个线程
        for (int i = 0; i < 10; i++) {
            Future<LocalDate> submit = pool.submit(localDateCallable);
            list1.add(submit);
        }
        //打印结果
        for (Future future : list) {
            System.out.println(future.get());
        }
        pool.shutdown();
    }
    }

2、本地化日期时间APl

LocalDate
LocalTime
LocalDateTime
public class Demo1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //1、创建本地时间
        LocalDateTime localDateTime = LocalDateTime.now();

        //2、自定义时间
        LocalDateTime of = LocalDateTime.of(2020, 10, 12, 9, 10);
        System.out.println(localDateTime.getYear());
        System.out.println(localDateTime.getMonthValue());
        System.out.println(localDateTime.getDayOfMonth());
        System.out.println(localDateTime.getDayOfMonth());

        //3、添加两天
        LocalDateTime localDateTime1 = localDateTime.plusDays(2);
        System.out.println(localDateTime1);

        //4、减少一个月
        LocalDateTime localDateTime2 = localDateTime.minusMonths(1);
        System.out.println(localDateTime2);
        
    }

}

3、Instant:时间戳

//1、创建Instant,时间戳
Instant instant = Instant.now();
System.out.println(instant.toString());
System.out.println(instant.toEpochMilli());
System.out.println(System.currentTimeMillis() );

//2、添加减少时间
Instant instant1 = instant.plusSeconds(10);
System.out.println(Duration.between(instant, instant1).toMillis());

4、ZoneId:时区

//3、ZoneId
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
for(String string : availableZoneIds){
    System.out.println(string);
}
System.out.println(ZoneId.systemDefault().toString());

5、Date、Instant、LocalDateTime的转换

//1、Date -> Instant -> LocalDateTime
Date date = new Date();
Instant instant2 = date.toInstant();
System.out.println(instant2);

LocalDateTime localDateTime = LocalDateTime.ofInstant(instant2, ZoneId.systemDefault());
System.out.println(localDateTime);

//2、LocalDateTime -> Instant -> Date
Instant instant3 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
System.out.println(instant3);
Date from = Date.from(instant3);
System.out.println(from);

6、DateTimeFormatter:格式化类

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//把时间转换成字符串
String format = dtf.format(LocalDateTime.now());
System.out.println(format);

//把字符串转换成时间
LocalDateTime parse = LocalDateTime.parse("2020-10-12 10:10:10", dtf);
System.out.println(parse);

八、总结

1、Lambda表达式:

​ 允许把函数作为一个方法参数传递

2、函数式接口使用:

​ Consumer消费型接口

​ Supplier供给型接口

​ Function函数型接口

​ predicate断言型接口

3、Stream API

​ 把对数据的操作封装成一个流

​ 步骤:创建、中间操作、终止操作

4、新时间API

posted @ 2020-11-19 13:56  李佳聪  阅读(127)  评论(0)    收藏  举报