Java8主要是在原来面向对象的基础上增加了函数式编程的能力。这样就出现了在Java中使用Lambda表达式,将一个函数作为方法的参数来进行传递。Java8的Stream就是典型的例子,Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
一、Stream API
filter
1、统计
long count = data.stream().filter(i -> i > 20).count();
结果:5
2、过滤转换
List<Integer> list = data.stream().filter(i -> i > 20).collect(Collectors.toList());
结果:[27, 23, 99, 232, 56]
3、findFirst()
Optional<Integer> optional = data.stream().filter(i -> Objects.equals(27, i)).findFirst();
if (optional.isPresent()) {
System.out.println("存在,值为:" + optional.get());
} else {
System.out.println("不存在");
}
结果:存在,值为:27
4、findAny()
可以在集合中只要找到任何一个所匹配的元素,就返回
Integer any = data.stream().filter(i -> i > 50).findAny().get();
结果:99
Arrays.stream()
long count1 = Arrays.stream(arr).filter(i -> i > 20).count();
结果:7
Stream.of()
long count2 = Stream.of(arr).filter(i -> i > 20).count();
long sum = Stream.of(12, 77, 59, 3, 654).filter(i -> i > 20).mapToInt(Integer::intValue).sum();
System.out.println("count:" + count2 + ",sum:" + sum);
结果:count:7,sum:790
Stream.generate()
用来创建无限Stream的静态方法
Stream<String> stream = Stream.generate(() -> "test").limit(10);
String[] strArr = stream.toArray(String[]::new);
System.out.println(Arrays.toString(strArr));
结果:[test, test, test, test, test, test, test, test, test, test]
Stream.iterate()
用来创建无限Stream的静态方法
Stream<BigInteger> bigIntStream = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.TEN)).limit(10);
BigInteger[] bigIntArr = bigIntStream.toArray(BigInteger[]::new);
System.out.println(Arrays.toString(bigIntArr));
结果:[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
map方法
将Integer类型转换成String类型
List<String> afterString = data.stream().map(i -> String.valueOf(i)).collect(Collectors.toList());
limit方法和skip方法
limit(n)方法会返回一个包含n个元素的新的流(若总长小于n则返回原始流) skip(n)方法正好相反,它会丢弃掉前面的n个元素。
List<Integer> list1 = data.stream().skip(4).limit(4).collect(Collectors.toList());
结果:[19, 27, 23, 99]
distinct方法
List<Integer> list2 = data.stream().distinct().collect(Collectors.toList());
结果:[3, 4, 8, 16, 19, 27, 23, 99, 15, 5, 232, 56]
sorted方法
1、自然升序
List<Integer> list3 = data.stream().sorted().collect(Collectors.toList());
2、自然序降
List<Integer> list4 = data.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
3、Comparator 自定义升序
List<Integer> list5 = data.stream().sorted(Comparator.comparing(Integer::intValue)).collect(Collectors.toList());
4、Comparator 自定义降序
List<Integer> list6 = data.stream().sorted(Comparator.comparing(Integer::intValue).reversed()).collect(Collectors.toList());
结果:[3, 4, 5, 8, 8, 15, 16, 19, 23, 27, 56, 99, 232]
[232, 99, 56, 27, 23, 19, 16, 15, 8, 8, 5, 4, 3]
[3, 4, 5, 8, 8, 15, 16, 19, 23, 27, 56, 99, 232]
[232, 99, 56, 27, 23, 19, 16, 15, 8, 8, 5, 4, 3]
聚合
1、max方法
Integer maxItem = data.stream().max(Integer::compareTo).get();
2、min方法
Integer minItem = data.stream().min(Integer::compareTo).get();
anyMatch方法
可以判定集合中是否还有匹配的元素
boolean b = data.parallelStream().allMatch(i -> i > 80);
allMatch方法
存在返回true
boolean all = data.parallelStream().allMatch(i -> i > 100);
noneMatch方法
不存在返回true
boolean none = data.parallelStream().noneMatch(i -> i > 100);
reduce方法
将流中的元素进行进一步计算的方法
1、求和
Integer sum1 = data.stream().reduce(Integer::sum).get();
2、对元素长度进行求和
Integer sum2 = data.stream().map(Objects::toString).mapToInt(String::length).sum();
收集到List中
List<Integer> list7 = data.stream().collect(Collectors.toList());
收集到Set中
Set<Integer> set = data.stream().collect(Collectors.toSet());
TreeSet<Integer> treeSet = data.stream().collect(Collectors.toCollection(TreeSet::new));
joining()
1、字符串连接
String str = afterString.stream().collect(Collectors.joining());
2、当流中的元素不是字符串时,需要先将流转成字符串流再进行拼接。
String str1 = data.stream().map(String::valueOf).collect(Collectors.joining(","));
收集聚合(总和、平均值、最大值、最小值)
int sum3 = data.stream().collect(Collectors.summingInt(Integer::intValue));
Double ave = data.stream().collect(Collectors.averagingInt(Integer::intValue));
Integer max = data.stream().collect(Collectors.maxBy(Integer::compare)).get();
Integer min = data.stream().collect(Collectors.minBy(Integer::compare)).get();
System.out.println("sum:" + sum3 + ",ave:" + ave + ",max:" + max + ",min:" + min);
结果:sum:515,ave:39.61538461538461,max:232,min:3
一次性收集流中的结果(总和、平均值、最大值、最小值)
IntSummaryStatistics summaryStatistics = data.stream().collect(Collectors.summarizingInt(Integer::intValue));
结果:IntSummaryStatistics{count=13, sum=515, min=3, average=39.615385, max=232}
集合转Map
Map<Integer, String> map = demos.stream().collect(Collectors.toMap(Demo::getId, Demo::getName));
当出现键冲突时只保留一个并且是保留已经存在的值时
Map<Integer, Demo> map1 = demos.stream().collect(Collectors.toMap(Demo::getId, Function.identity(), (nowValue, newValue) -> nowValue));
如果想指定生成的Map类型,则还需要第三个参数
TreeMap<Integer, Demo> roomTreeMap = demos.stream().collect(Collectors.toMap(Demo::getId, Function.identity(), (nowValue, newValue) -> newValue, TreeMap::new));
分组
Map<Integer, List<Demo>> groupMap = demos.stream().collect(Collectors.groupingBy(Demo::getAge));
结果:
{
20=[Demo(id=4, name=DDD, age=20)],
21=[Demo(id=2, name=BBB, age=21), Demo(id=5, name=EEE, age=21)],
24=[Demo(id=3, name=CCC, age=24)],
12=[Demo(id=1, name=AAA, age=12)]
}
分片
当分类函数是一个返回布尔值的函数时,流元素会被分为两组列表:一组是返回true的元素集合,另一组是返回false的元素集合。
Map<Boolean, List<Demo>> partitionMap = demos.stream().collect(Collectors.partitioningBy(d -> d.getAge() == 21));
结果:
{
false=[Demo(id=1, name=AAA, age=12), Demo(id=3, name=CCC, age=24), Demo(id=4, name=DDD, age=20)],
true=[Demo(id=2, name=BBB, age=21), Demo(id=5, name=EEE, age=21)]
}
分组统计
1、统计个数
Map<Integer, Long> countMap = demos.stream().collect(Collectors.groupingBy(Demo::getAge, Collectors.counting()));
2、计算总和
Map<Integer, Integer> sumMap = demos.stream().collect(Collectors.groupingBy(Demo::getAge, Collectors.summingInt(Demo::getAge)));
3、计算最大值
Map<String, Optional<Demo>> maxMap = demos.stream().collect(Collectors.groupingBy(Demo::getName, Collectors.maxBy(Comparator.comparing(Demo::getAge))));
4、计算最小值
Map<String, Optional<Demo>> minMap = demos.stream().collect(Collectors.groupingBy(Demo::getName, Collectors.minBy(Comparator.comparing(Demo::getAge))));
5、总和、平均值、总数、最大值、最小值
Map<String, IntSummaryStatistics> summaryStatisticsMap = demos.stream().collect(Collectors.groupingBy(Demo::getName, Collectors.summarizingInt(Demo::getAge)));
结果:
{
AAA=IntSummaryStatistics{count=1, sum=12, min=12, average=12.000000, max=12},
CCC=IntSummaryStatistics{count=1, sum=24, min=24, average=24.000000, max=24},
BBB=IntSummaryStatistics{count=1, sum=21, min=21, average=21.000000, max=21},
EEE=IntSummaryStatistics{count=1, sum=21, min=21, average=21.000000, max=21},
DDD=IntSummaryStatistics{count=1, sum=20, min=20, average=20.000000, max=20}
}
多级分组
Map<String, Map<Integer, List<Demo>>> multistageMap = demos.stream().collect(Collectors.groupingBy(Demo::getName, Collectors.groupingBy(Demo::getAge)));
结果:
{
"AAA":{
12:[{"age":12,"id":1,"name":"AAA"}]
},
"CCC":{
24:[{"age":24,"id":3,"name":"CCC"}]
},
"BBB":{
21:[{"age":21,"id":2,"name":"BBB"}]
},
"EEE":{
21:[{"age":21,"id":5,"name":"EEE"}]
},
"DDD":{
20:[{"age":20,"id":4,"name":"DDD"}]
}
}
以上列子测试数据
List<Integer> data = Arrays.asList(3,4,8,16,19,27,23,99,15,8,5,232,56);
Integer[] arr = new Integer[]{3, 4, 8, 16, 19, 27, 23, 99, 76, 232, 33, 96};
// --------------------------------------------
@Data
@Builder
class Demo {
private Integer id;
private String name;
private Integer age;
}
List<Demo> demos = Arrays.asList(
Demo.builder().id(1).name("AAA").age(12).build(),
Demo.builder().id(2).name("BBB").age(21).build(),
Demo.builder().id(3).name("CCC").age(24).build(),
Demo.builder().id(4).name("DDD").age(20).build(),
Demo.builder().id(5).name("EEE").age(21).build());
二、日期时间 API
当前日期
// 当前日期(yyyy-MM-dd)
LocalDate newDate = LocalDate.now();
当前时间
// 当前时间(HH:mm:ss)
LocalTime newTime = LocalTime.now();
当前日期时间
// 当前日期(yyyy-MM-dd HH:mm:ss)
LocalDateTime newDateTime = LocalDateTime.now();
计算时间或日期
1、获取过去n天或未来n天的日期 (plus()、minus())
// 获取7天前的日期
LocalDate date7_1 = newDate.minusDays(7);
// 获取7天后的日期
LocalDate date7_2 = newDate.plusDays(7);
2、获取过去n月或未来n月的日期
// 获取7个月前的日期
LocalDate month7_1 = newDate.minusMonths(7);
// 获取7个月后的日期
LocalDate month7_2 = newDate.plusMonths(7);
备注:在java.time.LocalTime和java.time.LocalDateTime中也有对应的plus()和minus()方法。
日期比较
日期比较(isBefore()、isAfter()),返回true或false
LocalDate newD = LocalDate.now();
LocalDate lsatD = newD.plusDays(1);
if (lsatD.isAfter(newD)) {
System.out.println("newD小于lsatD");
} else {
System.out.println("newD大于lsatD");
}
if (lsatD.isBefore(newD)) {
System.out.println("newD大于lsatD");
} else {
System.out.println("newD小于lsatD");
}
日期时间格式化
// 日期格式化为(yyyy-MM-dd)
String date1 = newDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// 日期格式化为(yyyyMMdd)
String date2 = newDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
// 日期格式化为(yyyy-MM)
String date3 = newDate.format(DateTimeFormatter.ofPattern("yyyy-MM"));
// 日期格式化为(yyyy-MM-dd HH:mm:ss)
String date4 = newDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
获取基本属性
// 年份
int year = newDate.getYear();
// 月份
int month = newDate.getMonthValue();
// 星期
int week = newDate.getDayOfWeek().getValue()
计算两个日期之间相差多少天
LocalDate localDate1 = LocalDate.of(2019, 8, 1);
LocalDate localDate2 = LocalDate.of(2019, 8, 20);
// 相差天数为
int num = (int) (localDate2.toEpochDay() - localDate1.toEpochDay());
// Period
Period period = Period.between(localDate1,localDate2);
// 相差多少年
period.getYears()
// 相差多少月
period.getMonths()
// 相差多少日 (一年内的)
period.getDays()
// 逻辑日历的天数
long days = ChronoUnit.DAYS.between(localDate1, localDate2);
Period中时间区间如果是2年1个月15天。那么通过getDays()方法获得就是第三个存储15天。而不是2年1个月15天总共有多少天。
想要逻辑日历的天数,使用DAYS.between()方法。
字符串转日期
LocalDate date = LocalDate.parse("2021-08-01");
获取某个时间在这个月的开始时间和结束时间
// 开始时间
LocalDate fistDate = LocalDate.parse("2019-08-28").with(TemporalAdjusters.firstDayOfMonth());
// 结束时间
LocalDate lastDate = LocalDate.parse("2019-08-28").with(TemporalAdjusters.lastDayOfMonth());
获取星期
LocalDate.parse("2021-08-28").getDayOfWeek()
判断是否是闰年
LocalDate.now().isLeapYear()
每天的开始时间、结束时间
// 开始时间
LocalTime.MIN
// 结束时间
LocalTime.MAX
获取毫秒值
Instant.now().toEpochMilli()
字符串转LocalDateTime
LocalDateTime.parse("2019-05-14 21:15:30.555", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
LocalDateTime转字符串
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(LocalDateTime.now())
原文始发于微信公众号(全栈客):Java8 常用 API
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/162672.html