Java8常用API方法


Lambda表达式

集合List的一些示例

提取list中的某个属性到list中,同时去重

List<Long> ids = list.stream().map(Member::getId).distinct().collect(Collectors.toList());

提取list中符合条件的数据

list = list.stream().filter(p->p.getAge()>25).collect(Collectors.toList());

提取list中的某个属性作为key

这种方式是基于map的,如果出现重复的key,那么需要设置舍弃方案,否则将会直接抛出异常。

Map<Long, Member> mapDemo2 = list.stream().collect(Collectors.toMap(Member::getId, Function.identity(), (k1, k2)->k1));

提取list中的某个属性为key,另外一个属性作为value

Map<Long, String> mapDemo3 = list.stream().collect(Collectors.toMap(Member::getId, Member::getName, (k1, k2)->k1));

list分组

Map<Long, List<Member>> mapGroup = list.stream().collect(Collectors.groupingBy(Member::getId));

list分组统计数量

Map<Long, Long> mapGroup = list.stream().collect(Collectors.groupingBy(Member::getId, Collectors.counting()));

list分组求和

求每个用户类型(type)的分数总值(score)

Map<Long, Long> mapGroup = list.stream().collect(Collectors.groupingBy(Member::getType, Collectors.summingInt(Member::getScore)));

list求和

BigDecimal sum = list.stream().map(Member::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);

list 排序

list.sort(Comparator.comparing(Member::getName, Comparator.nullsLast(String::compareTo))
        .thenComparing(Member::getMoney, Comparator.nullsLast(BigDecimal::compareTo)));

list.sort(Comparator.comparing(Member::getAge));

list.sort((Member m1, Member m2) -> {
    if (m1.getAge() > m2.getAge()) {
        return 1;
    } else if (m1.getAge() == m2.getAge()) {
        return 0;
    } else {
        return 0;
    }
});

list去重

直接根据整个对象来去重

list.stream().distinct().collect(Collectors.toList());

根据某个属性去重

list = list.stream().collect(Collectors.collectingAndThen(
        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Member::getId))), ArrayList::new));

日期时间对象

在Java8对日期对象进行重新封装,如:LocalDate(年月日)、LocalDateTime(年月日时分秒纳秒)、LocalTime(时分秒纳秒)、YearMonth(年月)、MonthDay(月日)。下面是它们的一些开发中可能比较常用的写法示例。

基本使用

// 获取当前日期
LocalDate nowDate = LocalDate.now();
// 获取当前日期+时间
LocalDateTime nowDateTime = LocalDateTime.now();
// 获取当前时间
LocalTime nowTime = LocalTime.now();

执行结果:

2021-05-14
2021-05-14T11:22:58.862
11:22:58.862

时间日期加减

年月日的加减法

对于年月日的加减算法在LocalDate 和 LocalDateTime中是一样的,下面是示例:

LocalDate nowDate = LocalDate.now();
// 加一天
nowDate = nowDate.plusDays(1);

// 加一月
nowDate = nowDate.plusMonths(1);

// 加一年
nowDate = nowDate.plusYears(1);

// 减法
nowDate = nowDate.plusYears(-1).plusMonths(-1).plusDays(-1);

// 周加减,就是加减7天
nowDate = nowDate.plusWeeks(1);

也可以使用minusXXX来做减法

时分秒纳秒的加减法

LocalDateTime nowDateTime = LocalDateTime.now();
// 小时的加减
nowDateTime = nowDateTime.plusHours(1);

// 分钟加减
nowDateTime = nowDateTime.plusMinutes(1);

// 秒加减
nowDateTime = nowDateTime.plusSeconds(1);

// 纳秒加减
nowDateTime = nowDateTime.plusNanos(1);

日期大小比较

下面只是LocalDate的,其他类型的比较方法是一样的。

LocalDate minDate = LocalDate.now();
LocalDate maxDate = minDate.plusDays(1);

// minDate < maxDate: 根据单词意思就是判断minDate是否在maxDate的前面
System.out.println(minDate.isBefore(maxDate));

// minDate > maxDate: 根据单词意思就是判断minDate是否在maxDate的后面
System.out.println(minDate.isAfter(maxDate));

// = : 相等
System.out.println(minDate.isEqual(minDate));

日期格式化

// 日期对象格式化字符串
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String str = now.format(dtf);

// 字符串格式化为日期对象
YearMonth yearMonth = YearMonth.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));

// 字符串格式化为日期对象
now = LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));

日期计算

时分秒计算

时分秒计算通常使用Duration(不支持LocalDate)来进行计算,注意Duration.between函数是用后面的减前面的;下面是一些示例

Duration duration = Duration.between(date1, date2);

// 相差小时数
long hours = duration.toHours();

//相差的分钟数
long minutes = duration.toMinutes();

//相差毫秒数
long millis = duration.toMillis();

// 相差秒数
long seconds = millis/1000;

注意在计算相差多少天时需要确定哈实际的需求,是计算实际距离多少天,还是只是日期上相差多少天。Duration中的toDay方法返回的是时间相差多少天;比如说date1是2021-05-14T23:00:00,date2是2021-05-15T00:00:00,那么使用toDay方法计算出来的值是0。

注意Duration函数是不支持LocalDate类型的,直接从源码来说明为什么;Duration的between方法里面里面会执行如下代码

startInclusive.until(endExclusive, NANOS)

这个startInclusive就是我们传入的日期中的一个;这个是在调用LocalDate的until方法,传入的unit单位是NANOS,但是LocalDate中的switch-case不支持这个类型,会直接抛出异常。

@Override
public long until(Temporal endExclusive, TemporalUnit unit) {
    LocalDate end = LocalDate.from(endExclusive);
    if (unit instanceof ChronoUnit) {
        switch ((ChronoUnit) unit) {
            case DAYS: return daysUntil(end);
            case WEEKS: return daysUntil(end) / 7;
            case MONTHS: return monthsUntil(end);
            case YEARS: return monthsUntil(end) / 12;
            case DECADES: return monthsUntil(end) / 120;
            case CENTURIES: return monthsUntil(end) / 1200;
            case MILLENNIA: return monthsUntil(end) / 12000;
            case ERAS: return end.getLong(ERA) - getLong(ERA);
        }
        throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
    }
    return unit.between(this, end);
}

年月日计算

注意Java8提供的Period函数是将整个时间间距转换为了年月日。比如2个日期相差13个月,那么会被转换为1年1个月,因此不建议用这个函数来计算相关的天数。虽然它也可以计算(比如同一个月的可以正常计算相差的天数,同一年的可以计算相差的月数)。

  • 相差的天数
long day = end.toEpochDay()-start.toEpochDay();
  • 相差月份数
// 相差的月数
long month = (end.getYear()* 12L +end.getMonth().getValue()) - (start.getYear()* 12L +start.getMonth().getValue());
  • 相差年份数
// 相差的年份数
long year = end.getYear() - start.getYear();
  • 计算相差的年月日
Period period = Period.between(start, end);
System.out.println("相差"+period.getYears()+"年"+period.getMonths()+"个月"+period.getDays()+"天");

一些特殊的需求

根据指定的年月日时分秒来来创建日期

// 指定日期:年 月 日
LocalDate date = LocalDate.of(2021, 5, 14);

// 指定日期:年 月 日 时 分 秒 纳秒
LocalDateTime dateTime = LocalDateTime.of(2021, 5, 14, 12, 25, 30);

获取月份的最后一天

LocalDate firstDate = LocalDate.of(2020, 9, 1);

// 设置为当月最后一天
LocalDate lastDate = firstDate.with(TemporalAdjusters.lastDayOfMonth());

获取本周指定周几的日期

// 获取本周周一的日期
LocalDate firstDay = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));

修改日期的年月日时分秒

LocalDate date1 = date.withYear(2022).withMonth(2).withDayOfMonth(28);

LocalDateTime和时间戳的相互转换

// 获取时间
LocalDateTime date = LocalDate.now().atTime(LocalTime.MIN);
// 获取该时间的时间戳;因为我们国家这里是东八区因此偏移是8小时
long timestamp  = date.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
// 将时间戳转换为LocalDateTime
date = Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();

其他

Java还定义了一些常用的常量,具体可以直接到源码中去查看即可。

// MIDNIGHT 就是 00:00
LocalDateTime tomorrowMidnight = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT).plusDays(1);

特别提醒:扫码关注微信订阅号'起岸星辰',实时掌握IT业界技术资讯! 转载请保留原文中的链接!
  目录