java8(一)

1、Stream流及API使用

1、stream的操作三步骤
  • 创建Stream

    ​ 一个数据源(如:集合、数组),获取一个流

  • 中间操作

    ​ 一个中间操作链,对数据源的数据进行处理

  • 终止操作(终端操作)

    ​ 一个终止操作,执行中间操作链,并产生结果

2、筛选 / 切片

中间操作:

  • filter:接收 Lambda ,从流中排除某些元素
  • limit:截断流,使其元素不超过给定数量
  • skip(n):跳过元素,返回一个舍弃了前n个元素的流;若流中元素不足n个,则返回一个空流;与 limit(n) 互补
  • distinct:筛选,通过流所生成的 hashCode() 与 equals() 取除重复元素
    在这里插入图片描述

​ 中间操作:不会执行任何操作

​ 终止操作:一次性执行全部内容,即“惰性求值”。

2.1 filter:排除元素
    @Test
    public void test02(){
        List<Employee> employees = getList();
        Stream<Employee> employeeStream = employees.stream().filter((e -> {
            System.out.println("中间操作");
            return e.getAge() > 35;
        }));
        employeeStream.forEach(System.out::println);
    }

内部迭代:迭代操作由Stream API完成

外部迭代:我们通过迭代器完成

// 外部迭代
	@Test
    public void test03(){
        List<Employee> employees = getList();
        Iterator<Employee> iterator = employees.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
2.2 短路,提高效率

​ 短路:是找到想要的数据后就不在找,这样可提高遍历的效率

	@Test
    public void test05(){
        List<Employee> employees = getList();
        employees.stream().filter((e) -> {
            System.out.println("短路!");
            return e.getSalay() > 5000;
                    }).limit(2).forEach(System.out::println);
    }

打印结果:
在这里插入图片描述
以上“短路”只打印了两次,说明只遍历了两次操作,找到想要的数据后,就不在继续向下遍历了,可大大提高遍历的效率。

2.3 distinct去重
public List<Employee> getList(){
        List<Employee> employees = Arrays.asList(
        		new Employee("张三", 18, 8999.99),
                new Employee("李四", 24, 6787.99),
                new Employee("jack", 56, 3849.90),
                new Employee("mark", 38, 7648.99),
                new Employee("mark", 38, 7648.99),
                new Employee("mark", 38, 7648.99),
                new Employee("mark", 38, 7648.99));
        return employees;
    }

	@Test
    public void test06(){
        List<Employee> employees = getList();
        employees.stream().filter((e) -> e.getSalay() > 5000).distinct().forEach(System.out::println);
    }

打印结果:
在这里插入图片描述

2.4 映射
  • map:接收 Lambda ,将元素转换为其他形式或提取信息;接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
@Test
    public void test07(){
        List<String> list = Arrays.asList("aaa","bbb","ccc","ddd");
        list.stream().map((str) -> str.toUpperCase()).forEach(System.out::println);
    }

返回结果:
AAA
BBB
CCC
DDD  
2.5 排序
  • sorted():自然排序

  • sorted(Comparator c):定制排序

    	/**
         * 自然排序 - sort
         * sorted() - 自然排序(Comparable)
         * sorted(Comparator com) - 定制排序
         */
        @Test
        public void test08(){   
            List<String> list = Arrays.asList("ccc", "aaa", "ddd", "bbb");
            list.stream().sorted().forEach(System.out::println);
    
            System.out.println("-------------------------------");
    
            List<Employee> employees = getList();
            employees.stream().sorted((e1,e2) ->{
                if(e1.getAge() == e2.getAge()){
                    return e1.getName().compareTo(e2.getName());
                }else{
                    return e1.getAge().compareTo(e2.getAge());
                }
            }).forEach(System.out::println);
        }
    

    打印结果:
    在这里插入图片描述

2.6 查找 / 匹配

终止操作:

  • allMatch:检查是否匹配所有元素
  • anyMatch:检查是否至少匹配一个元素
  • noneMatch:检查是否没有匹配所有元素
  • findFirst:返回第一个元素
  • findAny:返回当前流中的任意元素
  • count:返回流中元素的总个数
  • max:返回流中最大值
  • min:返回流中最小值

1)检查相关操作

/**
     * 检查相关操作
     */
    @Test
    public void test01(){
        List<Employee> employees = getList();
        boolean b = employees.stream().allMatch((e) -> e.getStatus().equals(Employee.Status.FREE));
        System.out.println(b);
        System.out.println("-------------------------");

        boolean b1 = employees.stream().anyMatch((e) -> e.getStatus().equals(Employee.Status.FREE));
        System.out.println(b1);
        System.out.println("-------------------------");

        Optional<Employee> op = employees.stream().sorted((e1,e2) -> 		Double.compare(e1.getSalay(),e2.getSalay())).findFirst();
        System.out.println(op.get());
        System.out.println("-------------------------");

        Optional<Employee> employee = employees.stream()
                .filter((e) -> e.getStatus().equals(Employee.Status.FREE))
                .findAny();
        System.out.println(employee);
    }

2)汇总、最大值和最小值

	/**
     * 最大值和最小值
     */
    @Test
    public void test02(){
        List<Employee> employees = getList();
        long count = employees.stream().count();
        System.out.println(count);

        // 返回工资最大值的那条数据
        System.out.println("--------------------");
        Optional<Employee> employee = employees.stream().max((e1, e2) -> Double.compare(e1.getSalay(), e2.getSalay()));
        System.out.println(employee.get());

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

        // 获取最小工资数:先map找到所有的工资,再从这些里面找到工资数最小的那个值
        Optional<Double> op = employees.stream().map(Employee::getSalay).min(Double::compare);
        System.out.println(op.get());
    }
2.7 规约 / 收集

1)reduce:可以将流中元素反复结合起来,得到一个值

/**
     * 规约:
     *   reduce:可以将流中元素反复结合起来,得到一个值
     */
    @Test
    public void test01(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 累加的过程
        Integer reduce = list.stream().reduce(0, (x, y) -> x + y);
        System.out.println(reduce);

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

        /**
         * 计算员工集合中工资的总和
         */
        List<Employee> employees = getList();
        // 因为可能工资可能为空,所有返回的是Optional类型,防止空指针异常
        Optional<Double> reduce1 = employees.stream().map(Employee::getSalay).reduce(Double::sum);
        System.out.println(reduce1.get());
    }

打印结果:
在这里插入图片描述

2)收集:collect将流转换成其他形式;接收一个Collector接口的实现,用于给流元素做汇总方法

@Test
    public void test03(){
        // 获取员工总数
        List<Employee> employees = getList();
        Long count = employees.stream().collect(Collectors.counting());
        System.out.println(count);

        // 平均值
        Double avg = employees.stream().collect(Collectors.averagingDouble(Employee::getSalay));
        System.out.println(avg);

        // 总和
        Double sum = employees.stream().collect(Collectors.summingDouble(Employee::getSalay));
        System.out.println(sum);

        // 最大值
        Optional<Employee> max = employees.stream().collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalay(), e2.getSalay())));
        System.out.println(max.get());

        // 最小值
        Optional<Double> collect = employees.stream().map(Employee::getSalay).collect(Collectors.minBy(Double::compare));
        System.out.println(collect.get());
    }

打印结果:
在这里插入图片描述

2、Optional类

1、Optional类概念

​ Optional类(java.util.Optional)是一个容器类,代表一个值存在或不存在,原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并可以避免空指针异常

2、常用方法
  • Optional.of(T t):创建一个 Optional 实例
  • Optional.empty(T t):创建一个空的 Optional 实例
  • Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则空实例
  • isPresent():判断是否包含某值
  • orElse(T t):如果调用对象包含值,返回该值,否则返回 t
  • orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回 s 获取的值
  • map(Function f):如果有值对其处理,并返回处理后的 Optional,否则返回 Optional.empty()
  • flatmap(Function mapper):与 map 相似,要求返回值必须是 Optional

1)of()方法:创建一个 Optional 实例

    @Test
    public void test01(){
        Optional<Employee> optional = Optional.of(new Employee("张三"));
        Employee employee = optional.get();
        log.info("返回结果:{}", employee);
    }

打印结果:
在这里插入图片描述

2)empty(T t)方法:创建一个空的 Optional 实例

	@Test
    public void test02(){
        Optional<Employee> optional = Optional.empty();
        log.info("返回结果:{}",optional.get());
    }

3)isPresent():判断是否包含某值

	@Test
    public void test03(){
        Optional<Employee> optional = Optional.ofNullable(new Employee());
        if(optional.isPresent()){
            log.info("返回结果:{}",optional.get());
        }
    }

4)orElse(T t):如果调用对象包含值,返回该值,否则返回 t

	@Test
    public void test04(){
        Optional<Employee> optional = Optional.ofNullable(null);
        if(optional.isPresent()){
            log.info("返回结果:{}",optional.get());
        }

        Employee emp = optional.orElse(new Employee("张三", 28, 888.99, Employee.Status.FREE));
        log.info("返回结果:{}",emp);
    }

打印结果:
在这里插入图片描述

3、使用案例

1、Man类

@Data
public class Man {

    private Optional<Godness> godness = Optional.empty();

    public Man() {
    }

    public Man(Optional<Godness> godness) {
        this.godness = godness;
    }
}

2、Godness类

@Data
public class Godness {

    private String name;

    public Godness(String name) {
        this.name = name;
    }
}

3、寻找女神

以下代码的写法就可以避免空指针异常的情况

    @Test
    public void test05(){
        Optional<Godness> godness = Optional.ofNullable(new Godness("aaa"));
        Optional<Man> man = Optional.ofNullable(new Man(godness));
        String godnessName = getGodnessName(man);
        log.info("女神的名字:{}",godnessName);
    }

    //需求:获取一个男人心中女神的名字
	// 如果传入的参数为null,则新创建一个对象
    public String getGodnessName(Optional<Man> man){
        return man.orElse(new Man())
                  .getGodness()
                  .orElse(new Godness("苍老师"))
                  .getName();
    }

3、Date/Time API

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

    注:ISO-8601日历系统是国际标准化组织指定的现代公民的日期和时间的表示法。

    常用方法:

    方法名返回值类型解释
    now( )static LocalDateTime从默认时区的系统时钟获取当前日期
    of(int year, int month, int dayOfMonth, int hour, int minute, int second)static LocalDateTime从年,月,日,小时,分钟和秒获得 LocalDateTime的实例,将纳秒设置为零
    plus(long amountToAdd, TemporalUnit unit)LocalDateTime返回此日期时间的副本,并添加指定的数量
    get(TemporalField field)int从此日期时间获取指定字段的值为 int
    	@Test
        public void test01(){
            //获取当前时间日期 now
            LocalDateTime now = LocalDateTime.now();
            log.info("当前时间:{}", now); // 2022-02-18T16:38:55.687
    
            // 指定时间日期 of
            LocalDateTime of = LocalDateTime.of(2022, 02, 18, 16, 31, 24);
            log.info("指定时间日期:{}", of); // 2022-02-18T16:31:24
    
            // 加 plus 指定时间日期加一天
            LocalDateTime localDateTime = of.plusDays(1);
            log.info("指定时间日期+1天:{}", localDateTime); // 2022-02-19T16:31:24
    
            // 减 minus 指定时间日期减一天
            LocalDateTime minus = of.minusDays(1);
            log.info("指定时间日期-1天:{}", minus); // 2022-02-17T16:31:24
    
            //获取指定的你年月日时分秒... get
            log.info("获取指定的你年月日时分秒:{}", now.getDayOfYear());
            log.info("获取小时:{}", now.getHour());
            log.info("获取秒钟:{}", now.getSecond());
            log.info("获取月份:{}", now.getMonth());
        }
    
3.2 时间/日期 差
  • Duration:计算两个时间之间的间隔
  • Period:计算两个日期之间的间隔
@Test
public void test03(){
    //计算两个时间之间的间隔 between
    Instant ins1 = Instant.now();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Instant ins2 = Instant.now();
    Duration dura1 = Duration.between(ins1, ins2);
    System.out.println(dura1.getSeconds());
    System.out.println(dura1.toMillis());
}

@Test
public void test04(){
    LocalDate ld1 = LocalDate.of(2016, 9, 1);
    LocalDate ld2 = LocalDate.now();
    Period period = Period.between(ld1, ld2);  // ISO 标准
    System.out.println(period.getYears());
    System.out.println(period.toTotalMonths());
}

3.3 时间校正器

在这里插入图片描述

	/**
     * TimporalAdjuster:时间校正器
     */
    @Test
    public void test05(){
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);

        // 获取下一个周五的时间
        LocalDateTime ldt2 = ldt.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
        System.out.println(ldt2);

        // 自定义:下一个工作日
        LocalDateTime ldt4 = ldt.with((l) -> {
            LocalDateTime ldt3 = (LocalDateTime) l;
            DayOfWeek week = ldt3.getDayOfWeek();

            if (week.equals(DayOfWeek.FRIDAY)) {
                return ldt3.plusDays(3);
            } else if (week.equals(DayOfWeek.SATURDAY)) {
                return ldt3.plusDays(2);
            } else {
                return ldt3.plusDays(1);
            }
        });
        System.out.println("下一个工作日:" + ldt4);
    }
3.4 时间格式化
  • DateTimeFormatter:格式化时间 / 日期
    /**
     * DateTimeFormatter:格式化时间/日期
     */
    @Test
    public void test06(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE;
        String format = dtf.format(now);
        System.out.println(format); // 2022-02-18

        System.out.println("-------------------------");
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
        String format2 = dateTimeFormatter.format(now);
        System.out.println(format2); // 2022年02月18日 17:21:58
    }
3.5 时区
  • ZonedDate
  • ZonedTime
  • ZonedDateTime
@Test
public void test02(){
    //查看支持的时区
    Set<String> set = ZoneId.getAvailableZoneIds();
    set.forEach(System.out::println);

    //指定时区
    LocalDateTime ldt1 = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));
    System.out.println(ldt1);

    //在已构建好的日期时间上指定时区
    LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));
    ZonedDateTime zdt1 = ldt2.atZone(ZoneId.of("Europe/Tallinn"));
    System.out.println(zdt1);
}
3.6 Date与LocalDateTime之间的转换
  • 原则:利用时间戳Instant
@Test
public void test03(){
	// Date 转 LocalDateTime 
	Date date = new Date();
    Instant instant = date.toInstant();
    ZoneId zoneId = ZoneId.systemDefault();
    LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();

	// LocalDateTime 转 Date
	LocalDateTime localDateTime = LocalDateTime.now();
	ZoneId zoneId = ZoneId.systemDefault();
    ZonedDateTime zdt = localDateTime.atZone(zoneId);
    Date date = Date.from(zdt.toInstant());
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值