Java8

1、Lambda 表达式

  1. 概念描述

Lambda 是一个匿名函数, 我们可以把 Lambda表达式理解为是一段可以传递的代码 。

  1. 语法表达式

类型推断:Lambda 表达式中无需指定类型, 程序依然可以编译, 这是因为 javac 根据程序的上下文, 在后台推断出了参数的类型。 Lambda 表达式的类型依赖于上下文环境, 是由编译器推断出来的。

2、函数式接口

  1. Java 四大核心函数式接口

3. 方法与构造器引用

4 Stream API

  1. Stream 操作的三个步骤

创建Stream -> 中间操作 -> 终止操作

package con.andrew.demo.java8;

import com.sun.org.apache.xpath.internal.operations.Bool;
import con.andrew.demo.domain.Employee;
import con.andrew.demo.domain.Person;

import java.lang.reflect.Field;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import java.util.stream.Stream;

/**
 * 中间操作
 *
 * 筛选与切片
 *
 * <p> filter 接收 lambda ,从流中过滤某些元素
 * limit 截取流,使其元素不超过指定数量
 * skip 跳过元素,返回一个扔掉前 n 个元素的流。若流中元素不足 n 个,则返回一个空流
 * distinct 筛选,通过流所生成的元素 hasCode 和 equal 去除重复元素
 *
 *
 * 映射
 * map 接收 lambda ,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被映射到每个元素上,并将其映射成一个新的元素
 * flatMap 接收一个函数作为参数,将流中的每个值转换为另一个流,再拼接所有流
 *
 * 排序
 * sorted() 自然排序
 * sorted(comparator com) 定制排序
 *
 * 查找与匹配
 * allMatch 检查是否匹配所有元素
 * anyMatch 检查是否至少匹配一个元素
 * noneMatch 检查是否没有匹配所有元素
 * findFirst 返回第一个元素
 * findAny 返回当前流中的任意元素
 * count 返回流中元素的总个数
 * max 返回流中最大值
 * min 返回流中最小值
 *
 * 规约
 * reduce(T identity, BinaryOperator) / reduce(BinaryOperator) 将流中元素反复结合起来,得到一个值
 *
 * 收集
 * collect 将流转换为其他形式,接收一个 Collector 接口的实现,用于给 Stream 中元素汇总的方法
 */
public class StreamStudy {

    List<Employee> employees = Arrays.asList(
            new Employee("andrew", 18, "man"),
            new Employee("tom", 12, "man"));


    /**
     * 内部迭代
     */
    public void demo01() {
        Stream<Employee> stream = employees.stream()
                .filter(e -> {
                    System.out.println("中间操作");
                    return e.getAge() > 10;
                });

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

    /**
     * 外部迭代
     */
    public void demo02() {
        Iterator<Employee> iterator = employees.iterator();

        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

    /**
     * 字符串装箱
     *
     * @param str 输入字符串
     * @return 字符集合
     */
    public static Stream<Character> filterCharacter(String str) {
        List<Character> list = new ArrayList<>();

        for (Character character : str.toCharArray()) {
            list.add(character);
        }

        return list.stream();
    }


    /**
     * 映射
     */
    public void demo03() {
        List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");

        // {{a, a, a}, {b, b, b}, {c, c, c}}
        Stream<Stream<Character>> stream1= list.stream().map(StreamStudy::filterCharacter);
        stream1.forEach(stream -> {stream.forEach(System.out::println);});

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

        // {a, a, a, b, b, b, c, c, c}
        Stream<Character> stream2 = list.stream().flatMap(StreamStudy::filterCharacter);
        stream2.forEach(System.out::println);
    }

    /**
     * 排序
     */
    public void demo04() {
        List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");

        list.stream()
                .sorted()
                .forEach(System.out::println);

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

        employees.stream()
                .sorted((e1, e2) -> {
                    if (e1.getAge() == e2.getAge()) {
                        return e1.getName().compareTo(e2.getName());
                    } else {
                        return Integer.compare(e1.getAge(), e2.getAge());
                    }
                }).forEach(System.out::println);
    }


    /**
     * 规约操作
     */
    public void demo05() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);

        // 无累加初始值
        Optional<Integer> sum1 = list.stream().reduce((x, y) -> x + y);
        System.out.println(sum1.get());

        // 有累加初始值
        Integer sum2 = list.stream().reduce(10, (x, y) -> x + y);
        System.out.println(sum2);

        // 并行流
        String sum3 = Stream.of(1, 2, 3).parallel().reduce(String.valueOf("1"),
                (acc, i) -> String.valueOf(Integer.valueOf(acc)) + i,
                (acc1, acc2) -> String.valueOf(Integer.valueOf(acc1) + Integer.valueOf(acc2)));
        System.out.println(sum3);
    }

    /**
     * 收集
     */
    public void demo06() {
        // 转换为 list
        List<String> list = employees.stream().map(Employee::getName).collect(Collectors.toList());

        // 总数
        Long count = employees.stream().collect(Collectors.counting());

        // 平均值
        Double avg = employees.stream().collect(Collectors.averagingDouble(Employee::getAge));

        // 总和
        Double sum = employees.stream().collect(Collectors.summingDouble(Employee::getAge));

        // 最大值
        Optional<Employee> max = employees.stream().collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())));

        // 最小值
        Optional<Employee> min = employees.stream().collect(Collectors.minBy((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())));

        // 分组
        Map<Integer, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(Employee::getAge));

        // TODO 多级分组

        // 分区
        Map<Boolean, List<Employee>> map1 = employees.stream().collect(Collectors.partitioningBy(e -> e.getAge() > 10));

        // 整合运算资源
        DoubleSummaryStatistics doubleSummaryStatistics = employees.stream().collect(Collectors.summarizingDouble(Employee::getAge));

        // 连接符
        String str = employees.stream().map(Employee::getName).collect(Collectors.joining("==="));
    }


    /**
     * 并行流
     */
    public void demo07() {
        // 获取当前时间
        Instant start = Instant.now();

        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkJoinCalculate(0, 100000000L);
        Long sum = pool.invoke(task);

        Instant end = Instant.now();
        System.out.println("结果:" + sum + "耗时:" + Duration.between(start, end).toMillis());
        System.out.println("============并行流==========");

        LongStream.rangeClosed(0, 1000000000L).parallel().reduce(0, Long::sum);
    }

5. 并行流与串行流

并行流就是把一个内容分成多个数据块, 并用不同的线程分别处理每个数据块的流。

Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流之间进行切换

  1. Fork / Join 框架

6. 时间API

LocalDate、 LocalTime、 LocalDateTime 类的实例是不可变的对象, 分别表示使用 ISO-8601日历系统的日期、 时间、 日期和时间。 它们提供了简单的日期或时间, 并不包含当前的时间信息。 也不包含与时区相关的信息。

package con.andrew.demo.java8;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * Optional 容器类
 *
 * 接口允许有默认方法与静态方法
 *
 * 安全时间类
 *
 * TemporalAdjuster 时间校正器
 *
 */
public class OtherFeature {

    /**
     * 安全时间类
     *
     * @throws ExecutionException 执行异常
     * @throws InterruptedException 线程暂停异常
     */
    public void demo01() throws ExecutionException, InterruptedException {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyMMdd");

        Callable<LocalDate> task = new Callable<LocalDate>() {
            @Override
            public LocalDate call() throws Exception {
                return LocalDate.parse("20220723", dateTimeFormatter);
            }
        };

        ExecutorService executorService = Executors.newFixedThreadPool(10);

        List<Future<LocalDate>> results = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            results.add(executorService.submit(task));
        }

        for (Future<LocalDate> future : results) {
            System.out.println(future.get());
        }
    }

    /**
     * 获取两个日期之间的间隔
     */
    public void demo02() {
        // LocalDate LocalTime LocalDateTime

        // Instant 默认获取 UTC 时区
        Instant instant = Instant.now();
        System.out.println(instant);

        // 获取两个时间的间隔
        Instant instant1 = Instant.now();
        Instant instant2 = Instant.now();

        Duration between = Duration.between(instant1, instant2);
        System.out.println(between);

        // 获取两个日期之间的间隔
        LocalDate localDate1 =  LocalDate.of(2022, 10, 10);
        LocalDate localDate2 = LocalDate.now();

        Period period = Period.between(localDate1, localDate2);
        System.out.println(period);
    }


    /**
     * 时间校正器
     */
    public void demo03() {
        LocalDateTime localDateTime1 = LocalDateTime.now();
        System.out.println(localDateTime1);

        LocalDateTime localDateTime2 = localDateTime1.withDayOfMonth(10);
        System.out.println(localDateTime2);

        LocalDateTime localDateTime3 = localDateTime1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
        System.out.println(localDateTime3);

        // 自定义:下一个工作日
        LocalDateTime localDateTime5 = localDateTime1.with( localDateTime -> {
            LocalDateTime localDateTime4 = (LocalDateTime) localDateTime;

            DayOfWeek dayOfWeek = localDateTime4.getDayOfWeek();

            if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
                return localDateTime4.plusDays(3);
            } else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
                return localDateTime4.plusDays(2);
            } else {
                return localDateTime4.plusDays(1);
            }
        });

        System.out.println(localDateTime5);
    }

    /**
     * 时间格式化
     */
    public void demo04() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_DATE;
        LocalDateTime localDateTime = LocalDateTime.now();

        String str = dateTimeFormatter.format(localDateTime);
        System.out.println(str);
    }

    /**
     * 时区操作
     */
    public void demo05() {
        LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));
        System.out.println(localDateTime);
    }
}

7. Instant 时间戳

  • Duration:用于计算两个“时间” 间隔
  • Period:用于计算两个“日期” 间隔

8. 接口中的默认方法

9. 其他新特性

posted @ 2022-08-07 15:51  生活是很好玩的  阅读(168)  评论(0编辑  收藏  举报