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);