美文网首页程序员
优雅编程 - 语法糖

优雅编程 - 语法糖

作者: 林昀熙 | 来源:发表于2019-12-19 11:00 被阅读0次

    本篇采用示例的形式展示Java8的常见特性应用.

    线程写法

    Java8之前

    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("自定义线程");
        }
    }).start();
    

    Java8写法

    new Thread(()-> {
        System.out.println("自定义线程");
    }).start();
    

    比较器写法

    Java8之前

    List<String> list = Arrays.asList("bb", "a", "ccc");
    Collections.sort(list, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.length() - o2.length();
        }
    });
    // [a, bb, ccc]
    System.out.println(list);
    

    Java8写法

    Collections.sort(list, (o1, o2) -> o1.length() - o2.length());
    // [a, bb, ccc]
    System.out.println(list);
    

    遍历写法

    Java8之前

    List<String> list = Arrays.asList("bb", "a", "ccc");
    for (String li : list) {
        System.out.println(li);
    }
    

    Java8写法

    List<String> list = Arrays.asList("bb", "a", "ccc");
    list.forEach(li -> System.out.println(li));
    list.forEach(System.out::println);
    

    计算过滤

    List<Integer> numbers = Arrays.asList(20,22,1,2,1,3,3,2,4,8,16);
    // 过滤集合中的偶数,去重、排序
    List<Integer> filters = numbers.stream().filter(i -> i % 2 == 0).distinct().sorted().collect(Collectors.toList());
    // 248162022
    filters.forEach(System.out::print);
    

    对列表每个元素应用函数

    List<String> list = Arrays.asList("USA", "Japan", "France", "Germany", "Italy","Canada");
    // 将字符串换成大写并用点号链接起来
    String str = list.stream().map(x -> x.toUpperCase()).collect(Collectors.joining("、"));
    // USA、JAPAN、FRANCE、GERMANY、ITALY、CANADA
    System.out.println(str);
    

    lambda表达式中的Map Reduce

    List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400);
    double bill = costBeforeTax.stream().map((cost) -> cost + .10*cost).reduce((sum, cost) -> sum + cost).get();
    // 1100.0
    System.out.println("集合中的元素每个增大10%后的结果总和: " + bill);
    

    集合元素计算

    List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
    IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
    System.out.println("集合中最大值 : " + stats.getMax());
    System.out.println("集合中最小值 : " + stats.getMin());
    System.out.println("集合元素总数 : " + stats.getSum());
    System.out.println("集合元素均值 : " + stats.getAverage());
    

    集合元素分组

    public static void main(String[] args) {
       List<Person> list = Arrays.asList(new Person(10, "Elon"), new Person(12, "Dennisit"), new Person(10, "Alone"));
       // [{"age":10,"name":"Elon"}, {"age":12,"name":"Dennisit"}, {"age":10,"name":"Alone"}]
       System.out.println(list);
       Map<Integer, List<Person>> groupByAge = list.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.toList()));
       // {10=[{"age":10,"name":"Elon"}, {"age":10,"name":"Alone"}], 12=[{"age":12,"name":"Dennisit"}]}
       System.out.println(groupByAge);
       List<String> names = list.stream().map(e->e.getName()).collect(Collectors.toList());
       // [Elon, Dennisit, Alone]
       System.out.println(names);
       List<Integer> ages = list.stream().map(e->e.getAge()).distinct().collect(Collectors.toList());
       // [10, 12]
       System.out.println(ages);
    }
    
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    static class Person{
       private int age;
       private String name;
    
       public String toString(){
           return JSON.toJSONString(this);
       }
    }
    

    集合对象排序

    public static void main(String[] args) {
        List<Person> list = Arrays.asList(new Person(10, "Elon"), new Person(12, "Dennisit"), new Person(10, "Alone"));
        // 按照年龄降序
        List<Person> sort = list.stream()
                .sorted(Comparator.comparing(Person::getAge).reversed())
                .collect(Collectors.toList());
        // [{"age":12,"name":"Dennisit"}, {"age":10,"name":"Elon"}, {"age":10,"name":"Alone"}]
        System.out.println(sort);
    }
    

    函数式接口

    // 函数接口定义
    Predicate<String> startWithJ = (n) -> n.startsWith("J");
    Predicate<String> containedA = (n) -> n.contains("a");
    
    List<String> languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");
    // 使用逻辑函数合并Predicate 执行结果: Java,Scala,Haskell,
    languages.stream().filter(startWithJ.or(containedA)).forEach(li -> System.out.print(li + ","));
    

    函数接口应用

    我们在用全文索引的时候需要将数据先存储到索引然后进行搜索,索引数据一般操作有全量索引、增量索引、实施索引, 索引创建方式可能有databus、基于消息机制、或者基于定时任务等等.

    通常我们把DB数据转换为搜索引擎的索引的时候,分两步:

    • 筛选出待索引的数据
    • 将目标数据进行索引

    针对这个行为我们来定义行为规约, 函数接口定义时使用@FunctionalInterface

    筛选数据行为
    /**
     * 筛选数据行为规约
     */
    @FunctionalInterface
    public interface DataCriteria<T> {
    
        /**
         * 分页加载数据
         * @param page 页码
         * @param size 页量
         * @return 加载的数据集合
         */
        public List<T> loader(int page, int size);
    
    }
    
    索引数据行为规约
    /**
     * 索引数据行为规约
     */
    @FunctionalInterface
    public interface IndexCriteria {
    
        /**
         * 数据索引行为
         * @param list 待索引的数据
         * @return
         */
        public void index(List<?> list);
    
    }
    

    全量索引行为抽象

    
    /**
     * 每次批量处理的数据一次最大500个
     */
    public static final Integer DEFAULT_BATCH_SIZE = 500;
    
    /**
     * 私有化构造
     */
    private IndexAction(){
    
    }
    
    
    /**
     * 执行全量索引
     * @param dataCriteria 数据加载行为
     * @param indexCriteria 索引数据行为
     */
    public static void fullyIndex(DataCriteria dataCriteria, IndexCriteria indexCriteria) {
        fullyIndex(DEFAULT_BATCH_SIZE, dataCriteria, indexCriteria);
    }
    
    
    /**
     * 执行全量索引
     * @param size 每个批次索引的数据大小
     * @param dataCriteria 数据加载行为
     * @param indexCriteria 索引数据行为
     */
    public static void fullyIndex(int size, DataCriteria dataCriteria, IndexCriteria indexCriteria) {
        // 游标页从第一页开始
        int current = 1;
        // 约束批量处理的大小
        size = NumberUtils.restrainNum(size, 0, DEFAULT_BATCH_SIZE);
        while(true){
            int cursor = cursor(current, size, dataCriteria, indexCriteria);
            if (cursor == current) {
                LOG.info("[创建索引] 创建完成, {}*{}数据", size, cursor);
                break;
            }
            current = cursor;
        }
    }
    
    /**
     * 游标扫描处理
     * @param page 游标页
     * @param size 每个批次索引的数据大小
     * @param dataCriteria 数据加载行为
     * @param indexCriteria 索引数据行为
     * @return
     */
    private static int cursor(int page, int size, DataCriteria dataCriteria, IndexCriteria indexCriteria){
        Assert.notNull(dataCriteria, "数据操作不能为空");
        Assert.notNull(indexCriteria, "操作操作不能为空");
        List list = dataCriteria.loader(page, size);
        if(CollectionUtils.isNotEmpty(list)){
            indexCriteria.index(list);
            ++ page;
        }
        return page;
    }
    

    上面我们做了简单的全量索引行为抽象, 从第一页开始分页加载数据进行索引,直到我们加载到的数据为空,本次索引行为结束

    特定索引行为抽象

    /**
     * 指定数据索引
     * @param list 待索引数据
     * @param indexCriteria 索引行为
     */
    public static void pointIndex(List<?> list, IndexCriteria indexCriteria){
        if(CollectionUtils.isEmpty(list)){
            return;
        }
        Assert.notNull(indexCriteria, "操作操作不能为空");
        indexCriteria.index(list);
    }
    

    该抽象比较简单,直接进行指定的数据索引即可.

    规约使用

    上面我们定义了规约, 接下来直接展示如何优雅的基于规约装载数据

    /**
     * 全量索引
     */
    @Override
    public void fullyIndex() {
        IndexAction.fullyIndex(
                // 分页加载数据
                (p, s) -> {
                    return merchantService.selectList(p, s);
                },
                // 数据进行索引
                (x)-> merchantEsRepository.indexList((List<MerchantIndex>)x)
        );
    }
    
    /**
     * 特定索引
     * @param ids 主键编号集合
     * @throws Exception
     */
    @Override
    public void pointIndex(List<Integer> ids) throws Exception{
        List<MerchantIndex> list = merchantService.selectList(ids);
        IndexAction.pointIndex(list, (x) -> merchantEsRepository.indexList((List<MerchantIndex>) x));
    }
    

    示例中分别展示了全量索引和特定数据索引的规约应用,通过函数接口功能打包.我们把全量和增量的行为就隐藏在了规约行为中,使业务代码更简洁优雅.

    接口方法

    public static void main(String[] args) {
        MathOperation addition = (int a, int b) -> a + b;
        // 默认方法
        addition.print();
        // 9
        System.out.println(addition.operation(5, 4));
    }
    
    interface MathOperation {
    
        // 接口方法
        int operation(int a, int b);
    
        default void print(){
            System.out.println("默认方法");
        }
    }
    

    Java8日期操作

    /创建日期
    LocalDate date = LocalDate.of(2017,1,21); //2017-01-21
    int year = date.getYear() //2017
    Month month = date.getMonth(); //JANUARY
    int day = date.getDayOfMonth(); //21
    DayOfWeek dow = date.getDayOfWeek(); //SATURDAY
    int len = date.lengthOfMonth(); //31(days in January)
    boolean leap = date.isLeapYear(); //false(not a leap year)
    
    //时间的解析和格式化
    LocalDate date = LocalDate.parse("2017-01-21");
    LocalTime time = LocalTime.parse("13:45:20");
    
    LocalDateTime now = LocalDateTime.now();
    now.format(DateTimeFormatter.BASIC_ISO_DATE);
    
    //合并日期和时间
    LocalDateTime dt1 = LocalDateTime.of(2017, Month.JANUARY, 21, 18, 7);
    LocalDateTime dt2 = LocalDateTime.of(localDate, time);
    LocalDateTime dt3 = localDate.atTime(13,45,20);
    LocalDateTime dt4 = localDate.atTime(time);
    LocalDateTime dt5 = time.atDate(localDate);
    
    //操作日期
    LocalDate date1 = LocalDate.of(2014,3,18); //2014-3-18
    LocalDate date2 = date1.plusWeeks(1); //2014-3-25
    LocalDate date3 = date2.minusYears(3); //2011-3-25
    LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS); //2011-09-25
    

    日期格式化

    java.util.date和java.time.LocalDateTime格式化

    应用示例
    /**
    * 格式化日期
    * @param date 待格式化的日期
    * @param pattern 格式化正则
    * @return 格式化结果串
    */
    public static String format(Date date, String pattern){
       return new SimpleDateFormat(pattern).format(date);
    }
    
    /**
    * 格式化日期
    * @param localDateTime 待格式化的日期
    * @param pattern 格式化正式
    * @return 格式化结果串
    */
    public static String format(LocalDateTime localDateTime, String pattern){
       return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }
    
    /**
    * 格式化日期
    * @param localDate 待格式化的日期
    * @param pattern 格式化正则, 这里使用的类型 {@link LocalDate}, 所以正则只能设定到天
    * @return 格式化结果串
    */
    public static String format(LocalDate localDate, String pattern){
       return localDate.format(DateTimeFormatter.ofPattern(pattern));
    }
    
    示例测试
    // 2017-08-28 15:45:02
    System.out.println(format(new Date(), "yyyy-MM-dd HH:mm:ss"));
    // 2017-08-28 15:45:02
    System.out.println(format((LocalDateTime.now()), "yyyy-MM-dd HH:mm:ss"));
    // 2017-08-28
    System.out.println(format((LocalDateTime.now().toLocalDate()), "yyyy-MM-dd"));
    

    日期转换

    java.util.date和java.time.LocalDateTime互相转换

    应用示例
    /**
    * 将 {@link LocalDateTime} 转换成 {@link Date}
    * @param localDateTime {@link LocalDateTime} 待转换的日期
    * @return 转换成Date结果
    */
    public static Date from(LocalDateTime localDateTime){
       Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
       return Date.from(instant);
    }
    
    /**
    * 将 {@link Date} 转换成 {@link LocalDateTime}
    * @param date {@link Date} 待转换的日期
    * @return 转换成 {@link LocalDateTime} 结果
    */
    public static LocalDateTime from(Date date){
       return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }
    
    示例测试
    String patternTime = "yyyy-MM-dd HH:mm:ss";
    Date now = new Date();
    // 2017-08-28 14:47:10
    System.out.println(format(from(now), patternTime));
    // 2017-08-28 14:47:10
    System.out.println(format(from(LocalDateTime.now()), patternTime));
    

    日期区间集合

    计算两端日期之间内的日期天数集合

    示例代码
    /**
    * 获取{@link Date}在开始时间和结束时间内的日期时间段{@link Date}集合
    * @param start 开始时间
    * @param end 结束时间
    * @return 时间天数集合
    */
    public static List<Date> dateZones(Date start, Date end){
       return dateZones(from(start), from(end));
    }
    
    
    /**
    * 获取 {@link LocalDate} 在开始时间和结束时间内的日期时间段 {@link LocalDate} 集合
    * @param start 开始时间
    * @param end 结束时间
    * @return 时间集合
    */
    public static List<Date> dateZones(LocalDate start, LocalDate end){
       return Stream.iterate(start, x -> x.plusDays(1))
               .limit(ChronoUnit.DAYS.between(start, end) + 1)
               .map(e -> Date.from(e.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))
               .collect(Collectors.toList());
    }
    
        
    /**
    * 获取{@link LocalDateTime} 在开始时间和结束时间内的日期时间段{@link Date}集合
    * @param start 开始时间
    * @param end 结束时间
    * @return 时间天数集合
    */
    public static List<Date> dateZones(LocalDateTime start, LocalDateTime end){
       // 用起始时间作为流的源头,按照每次加一天的方式创建一个无限流
       return Stream.iterate(start.toLocalDate(), x -> x.plusDays(1))
               // 截断无限流,长度为起始时间和结束时间的差+1个
               .limit(ChronoUnit.DAYS.between(start, end) + 1)
               // 由于最后要的是字符串,所以map转换一下
               .map(e -> Date.from(e.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))
               // 把流收集为List
               .collect(Collectors.toList());
    }
    
    
    /**
    * 获取{@link Date}在开始时间和结束时间内的日期时间段{@link LocalDate}集合
    * @param start 开始时间
    * @param end 结束时间
    * @return 时间集合
    */
    public static List<LocalDate> localDateZones(Date start, Date end){
       return localDateZones(from(start), from(end));
    }
    
    
    /**
    * 获取 {@link LocalDate} 在开始时间和结束时间内的日期时间段 {@link LocalDate} 集合
    * @param start 开始时间
    * @param end 结束时间
    * @return 时间集合
    */
    public static List<LocalDate> localDateZones(LocalDate start, LocalDate end){
       return Stream.iterate(start, x -> x.plusDays(1))
               .limit(ChronoUnit.DAYS.between(start, end) + 1)
               .collect(Collectors.toList());
    }
    
    /**
    * 获取 {@link LocalDateTime} 在开始时间和结束时间内的日期时间段 {@link LocalDate} 集合
    * @param start 开始时间
    * @param end 结束时间
    * @return 时间集合
    */
    public static List<LocalDate> localDateZones(LocalDateTime start, LocalDateTime end){
       // 用起始时间作为流的源头,按照每次加一天的方式创建一个无限流
       return Stream.iterate(start.toLocalDate(), x -> x.plusDays(1))
               // 截断无限流,长度为起始时间和结束时间的差+1个
               .limit(ChronoUnit.DAYS.between(start, end) + 1)
               .map(e -> e.atStartOfDay().toLocalDate())
               // 把流收集为List
               .collect(Collectors.toList());
    }
    
    示例测试
    String patternDate = "yyyy-MM-dd";
    List<Date> dateList = Arrays.asList(new Date(2017-1900, 11, 30), new Date(2018-1900, 0, 3));
    
    // 2017-12-30
    System.out.println("开始时间:"  + format(dateList.get(0), patternDate) + ", 结束时间:" + format(dateList.get(1), patternDate));
    
    // [2017-12-30, 2017-12-31, 2018-01-01, 2018-01-02, 2018-01-03]
    System.out.println(dateZones(dateList.get(0), dateList.get(1)).stream().map(x -> format(x, patternDate)).collect(Collectors.toList()));
    // [2017-12-30, 2017-12-31, 2018-01-01, 2018-01-02, 2018-01-03]
    System.out.println(localDateZones(dateList.get(0), dateList.get(1)).stream().map(x -> format(x, patternDate)).collect(Collectors.toList()));
    
    
    LocalDateTime now = LocalDateTime.of(2017, Month.DECEMBER, 30, 0, 0, 0);
    
    // 2017-12-30
    System.out.println(format(now, patternDate));
    
    // [2017-12-30, 2017-12-31, 2018-01-01, 2018-01-02, 2018-01-03]
    System.out.println(dateZones(now, now.plus(4, ChronoUnit.DAYS))
          .stream().map(x -> format(x, patternDate)).collect(Collectors.toList()));
    
    // [2017-12-30, 2017-12-31, 2018-01-01, 2018-01-02, 2018-01-03]
    System.out.println(localDateZones(now, now.plus(4, ChronoUnit.DAYS))
          .stream().map(x -> format(x, patternDate)).collect(Collectors.toList()));
    
    // [2017-12-30, 2017-12-31, 2018-01-01, 2018-01-02, 2018-01-03]
    System.out.println(localDateZones(now.toLocalDate(), now.toLocalDate().plus(4, ChronoUnit.DAYS))
          .stream().map(x -> format(x, patternDate)).collect(Collectors.toList()));
    

    日期加减

    示例代码
    String patternDate = "yyyy-MM-dd HH:mm:ss";
    
    LocalDateTime now = LocalDateTime.of(2017, Month.DECEMBER, 30, 0, 0, 0);
    
    // 当前时间: 2017-12-30 00:00:00
    System.out.println("当前时间: " + format(now, patternDate));
    
    // 30秒前: 2017-12-29 23:59:30
    System.out.println("30秒前: " + format(now.plus(-30, ChronoUnit.SECONDS), patternDate));
    
    // 5分钟后: 2017-12-30 00:05:00
    System.out.println("5分钟后: " + format(now.plus(5, ChronoUnit.MINUTES), patternDate));
    
    // 2天前: 2017-12-28 00:00:00
    System.out.println("2天前: " + format(now.plus(-2, ChronoUnit.DAYS), patternDate));
    
    // 2天后: 2018-01-01 00:00:00
    System.out.println("2天后: " + format(now.plus(2, ChronoUnit.DAYS), patternDate));
    
    // 1周后: 2018-01-06 00:00:00
    System.out.println("1周后: " + format(now.plusWeeks(1), patternDate));
            
    // 1月前: 2017-11-30 00:00:00
    System.out.println("1月前: " + format(now.plus(-1, ChronoUnit.MONTHS), patternDate));
    
    // 1月后: 2018-01-30 00:00:00
    System.out.println("1月后: " + format(now.plus(1, ChronoUnit.MONTHS), patternDate));
    
    // 1年后: 2018-12-30 00:00:00
    System.out.println("1年后: " + format(now.plus(1, ChronoUnit.YEARS), patternDate));
    

    日期推算

    示例代码
    String patternDate = "yyyy-MM-dd";
    
    LocalDateTime now = LocalDateTime.of(2017, Month.DECEMBER, 30, 0, 0, 0);
    
    // 当前时间: 2017-12-30
    System.out.println("当前时间: " + format(now, patternDate) + " ,是否闰年: " + now.toLocalDate().isLeapYear());
    
    // 当前月份: 十二月
    System.out.println("当前月份: " + Month.from(now).getDisplayName(TextStyle.FULL, Locale.CHINA));
    
    // 当前星期: 星期六
    System.out.println("当前星期: " + DayOfWeek.from(now).getDisplayName(TextStyle.FULL, Locale.CHINA));
    
    // 需要注意:java8提供的获取的本周第一天和本周最后一天是西方的界定方式, 第一天是周末, 最后一天是周六, 和中国的不太一样
    // 本周初第一天:2017-12-24
    System.out.println("本周初第一天: " + format(now.with(WeekFields.of(Locale.CHINA).dayOfWeek(),1L), patternDate));
    
    // 本周最后一天:2017-12-30
    System.out.println("本周最后一天: " + format(now.with(WeekFields.of(Locale.CHINA).dayOfWeek(),7L), patternDate));
    
    // 本月初第一天:2017-12-01
    System.out.println("本月初第一天: " + format(now.with(TemporalAdjusters.firstDayOfMonth()), patternDate));
    
    // 本月最后一天:2017-12-31
    System.out.println("本月最后一天: " + format(now.with(TemporalAdjusters.lastDayOfMonth()), patternDate));
    
    // 本年最后一天:2017-01-01
    System.out.println("本年最后一天: " + format(now.with(TemporalAdjusters.firstDayOfYear()), patternDate));
    
    // 本年最后一天:2017-12-31
    System.out.println("本年最后一天: " + format(now.with(TemporalAdjusters.lastDayOfYear()), patternDate));
    

    Optional类说明

    Optional类的Javadoc描述如下:
    这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

    Optional基础对象处理

    示例代码

    // 有则返回, 无则由函数产生
    System.out.println(Optional.ofNullable(null).orElseGet(() -> Arrays.asList(1,2,3)));
    
    // 元素存在输出true,反之输出false
    System.out.println(Optional.ofNullable("Elon").isPresent());
    
    // 不为空时输出元素,反之输出“默认值”
    System.out.println(Optional.ofNullable("Elon").orElse("默认值"));
    
    // 元素存在输出元素,反之抛出异常
    System.out.println(Optional.ofNullable("Elon").orElseThrow(IllegalArgumentException::new));
    
    
    // 元素存在输出true,反之输出false
    System.out.println(Optional.ofNullable(null).isPresent());
    
    // 不为空时输出元素,反之输出“默认值”
    System.out.println(Optional.ofNullable(null).orElse("默认值"));
    
    // 元素存在输出元素,反之抛出异常
    System.out.println(Optional.ofNullable(null).orElseThrow(IllegalArgumentException::new));
    

    示例输出

    [1, 2, 3]
    true
    Elon
    Elon
    false
    默认值
    
    java.lang.IllegalArgumentException
        at java.util.Optional.orElseThrow(Optional.java:290)
        ...
    

    Optional基础集合处理

    示例代码

    List<Integer> list = Arrays.asList(1, 2, 3, 2, 5, 3);
    
    // 集合不为空的时候进行遍历去重,反之输出空集合
    System.out.println(Optional.ofNullable(list).orElse(Lists.newArrayList()).stream().distinct().collect(Collectors.toList()));
    
    // 集合不为空的时候进行遍历去重,反之抛出异常
    System.out.println(Optional.ofNullable(list).orElseThrow(IllegalArgumentException::new).stream().distinct().collect(Collectors.toList()));
    
    list = null;
    
    // 集合不为空的时候进行遍历去重,反之输出空集合
    System.out.println(Optional.ofNullable(list).orElse(Lists.newArrayList()).stream().distinct().collect(Collectors.toList()));
    
    // 集合不为空的时候进行遍历去重,反之抛出异常 IllegalArgumentException
    System.out.println(Optional.ofNullable(list).orElseThrow(IllegalArgumentException::new).stream().distinct().collect(Collectors.toList()));
    

    示例输出

    [1, 2, 3, 5]
    [1, 2, 3, 5]
    []
    
    java.lang.IllegalArgumentException
        at java.util.Optional.orElseThrow(Optional.java:290)
        ...
    

    Optional复杂集合处理

    示例代码

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ToString
    class Person{
    
       private String name;
       private int age;
    
       public String toString(){
           return JSON.toJSONString(this);
       }
    }
    
    @Test
    public void list(){
       Person person = null;
       System.out.println(Optional.ofNullable(person).map(x -> x.getName()).orElse("默认姓名"));
       System.out.println(Optional.ofNullable(person).map(x -> x.getAge()).orElse(18));
    
       List<Person> list = Arrays.asList(new Person("p1", 10), new Person("p2", 15));
    
       System.out.println("最大年龄用户:" + Optional.ofNullable(list).orElseThrow(NullPointerException:: new).stream().collect(Collectors.maxBy(Comparator.comparingInt(Person::getAge))).get());
       System.out.println("最大年龄数值:" + Optional.ofNullable(list).orElseThrow(NullPointerException:: new).stream().collect(Collectors.maxBy(Comparator.comparingInt(Person::getAge))).get().getAge());
       System.out.println("年龄均值数值:" + Optional.ofNullable(list).orElseThrow(NullPointerException:: new).stream().collect(Collectors.averagingInt(Person::getAge)));
    }
    

    示例输出

    默认姓名
    18
    最大年龄用户:{"age":15,"name":"p2"}
    最大年龄数值:15
    年龄均值数值:12.5
    

    Nashorn JavaScript引擎

    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("JavaScript");
    // jdk.nashorn.api.scripting.NashornScriptEngine
    System.out.println( engine.getClass().getName() );
    // Result:2.0
    System.out.println("Result:" + engine.eval("function f() { return 1; }; f() + 1;"));
    

    Base64支持

    final String text = "Base64 finally in Java 8!";
    final String encoded = Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8));
    System.out.println(encoded);
    final String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
    System.out.println(decoded);
    

    Java8新特性示例图

    [图片上传失败...(image-672dc3-1576724390193)]

    相关文章

      网友评论

        本文标题:优雅编程 - 语法糖

        本文链接:https://www.haomeiwen.com/subject/wbkmnctx.html