2014年3月发布,主要增加了lambda表达式,stream,新Date类
Lambda
- 含义:将函数作为参数传入方法,方法内可以在适当的时候执行此函数。
//Lambda函数对应一个@FunctionalInterface注解的接口,本质是实现此接口的方法。接口只能有一个对外方法。
- Lambda表达式
map.forEach((k,v)->{
System.out.println(k);
});
- 简写
map.forEach((k,v)->System.out.println(k));
StreamAPI
list.stream()将数据转换成流的形式,然后就可以对于流进行链式操作,其中操作分为中间操作和结束操作,结束操作只能有一个。
- 流有原始流(IntStream...)boxed流(Stream<Interger>)
IntStream.boxed();//转换
Stream.mapToInt()...//转换
原始流没有数据收集的方法(.collect(Collectors.toList()))可以转换成boxed流然后收集
除了通过数据生成流,也可以随机生成
IntStream.range(1, 100).boxed().collect(Collectors.toList());
序号 | 中间操作 | 结束操作 |
---|---|---|
1 | filter | foreach |
2 | map、mapToInt、mapToDouble、mapToLong | collect |
3 | flatMap、flatMapToInt、flatMapToLong、flatMapToDouble | anyMatch |
4 | distinct | allMatch |
5 | sorted | noneMatch |
6 | skip | reduce |
7 | peek | min |
8 | limit | max |
9 | of | count |
10 | iterate | toArray |
11 | generate | forEachOrdered |
12 | empty | findFirst |
13 | concat | findAny |
中间操作
-
filter
过滤
//返回true的方向,否则拦截
list.stream().filter(e->e.equals("1")).forEach(System.out::println);
-
map
转换集合
同类有:mapToInt
、mapToDouble
、mapToLong
//int类型的id转换成string,即方法接收值之后可以返回其它类型的值并传递下去
idList.stream().map(Student::getName).collect(Collectors.toList())
.forEach(System.out::println);
mapToInt
IntStream intStream = list.stream().mapToInt(Student::getAge);
-
flatMap
将流中的元素也转换成流,加入到流中
同类有:flatMapToInt
、flatMapToLong
、flatMapToDouble
List<String> list2 = new ArrayList<>();
list2.add("aaa bbb ccc");
list2.add("ddd eee fff");
list2.add("ggg hhh iii");
list2 = list2.stream().map(s -> s.split(" ")).flatMap(Arrays::stream).collect(Collectors.toList());
-
distinct
去重
list.add("1");
list.add("1");
list.add("2");
list.stream().distinct().forEach(System.out::println);
-
sorted
排序
//asc排序
list.stream().sorted(Comparator.comparingInt(Student::getAge)).forEach(System.out::println);
System.out.println("------------------------------------------------------------------");
//desc排序
list.stream().sorted(Comparator.comparingInt(Student::getAge).reversed()).forEach(System.out::println);
-
skip
跳过前n个
list.stream().skip(1).forEach(System.out::println);
-
peek
生成副本
//和forEach类似,只是不影响源数据,并且是中间操作
List<String> list = new ArrayList();
list.add("123");
list.add("456");
List l = list.stream().peek(v-> {
v = v + "zzz";
}).collect(Collectors.toList());
l.forEach(System.out::println);
-
limit
截取前n个
list.stream().limit(1).forEach(System.out::println);
of
生成流iterate
生成流
List<String> list = Arrays.asList("a", "b", "c", "c", "d", "f", "a");
//从0开始,每次加1,生成list长度的流
Stream.iterate(0, i -> i + 1).limit(list.size()).forEach(i -> {
System.out.println(String.valueOf(i) + list.get(i));
});
-
generate
生成指定流
Stream<String> stream = Stream.generate(()->"user").limit(20);
stream.forEach(System.out::println);
empty
生成空流concat
连接两个流
List<String> list = Arrays.asList("a", "b", "c", "c", "d", "f", "a");
Stream.concat(list.stream(),list.stream()).forEach(System.out::println);
结束操作
-
foreach
遍历
//直接将值作为函数的输入值可以使用 类::方法 的形式
list.forEach(System.out::println);
-
collect
转换成集合
//过滤空元素
list.filter(StringUtil::isNotBlank).collect(Collectors.toList());
-
anyMatch
是否有一个满足条件
boolean isHave = list.stream().anyMatch(student -> student.getAge() == 16);
-
allMatch
是否全部满足
boolean isHave = list.stream().allMatch(student -> student.getAge() == 16);
-
noneMatch
都不符合
boolean isHave = list.stream().noneMatch(student -> student.getAge() == 16);
-
reduce
每个元素的返回值传入下个元素中
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
// 计算总和,count是每次返回的数,都会传入下一个元素里。
// v是当前元素的值。0是count的初始值,没有初始化值返回的是Optional
int total = list.stream().reduce(0,(count,v)->{
return count+v;
});
min
最小的max
最大的count
计数
long count = list.stream().count();
-
toArray
转换成数组
toArray(Integer[] :: new)//转换成Interger[]
toArray(person[] :: new)//对象数组
-
forEachOrdered
遍历,顺序一定和元素顺序一样
//和forEach一样,遍历流,不过这个执行顺序一定和流顺序一样
list.forEachOrdered();
-
findFirst
找到第一个元素
Optional<Student> student = list.stream().findFirst();
-
findAny
找到其中一个元素 (使用 stream() 时找到的是第一个元素;使用 parallelStream() 并行时找到的是其中一个元素)
Optional<Student> student = list.stream().findAny();
新增了时间类型
- 新增的
api
本地日期和时间
LocalDateTime
LocalDate
LocalTime
本地时间指的是经过时区偏移量计算过的时间,其本身不带时区内容。
比如12:00
,无法分辨是那个时区的12:00
.带有时区的日期时间
ZonedDateTime
本地时间通过设置时区或偏移可以换算成这个。
时间戳设置时区或偏移量也可以转换。时刻(时间戳)
Instant
时区
ZoneId
ZoneOffset
时间间隔
Duration
线程安全的格式化工具
DateTimeFormatter
- 新API修正了旧API不合理的常量设计:
- Month的范围用1~12表示1月到12月;
- Week的范围用1~7表示周一到周日。
时间类应用
- 毫秒数转时间
// 1. 声明可复用的时间格式化工具
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// 2. 毫秒转时间戳,时间戳设置时区成为带时区的时间类型(使用默认时区),带时区的时间类型转换成本地时间
LocalDate localDate = Instant.ofEpochMilli(millisecond).atZone(ZoneId.systemDefault()).toLocalDate();
// 3. 格式化本地时间
formatter.format(localDate)
- 获取当天时间(自带格式化)
// 现在的本地时间是 : 2019-01-05
LocalDate today = LocalDate.now();
System.out.println("现在的本地时间是 : " + today);
- 直接获取当前
- 年月日
LocalDate today = LocalDate.now();
int year = today.getYear();
int month = today.getMonthValue();
int day = today.getDayOfMonth();
System.out.printf("年: %d 月 : %d 日 : %d ", year, month, day);
- 时间
LocalTime time = LocalTime.now();
System.out.println("当前时间是 : " + time);
- 构造指定日期
LocalDate dateOfBirth = LocalDate.of(2018, 04, 01);
System.out.println("你的生日是 : " + dateOfBirth);
- 日期比较
- 比较年月日都是否相等
LocalDate date1 = LocalDate.of(2018, 04, 01);
LocalDate today = LocalDate.now();
System.out.println("date1和今天是同一天吗?:"+ date1.equals(today));
- 忽略年
LocalDate dateOfBirth = LocalDate.of(2018, 04, 01);
MonthDay birthday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth());
MonthDay currentMonthDay = MonthDay.from(today);
System.out.println("今天是4月1日吗?" + currentMonthDay.equals(birthday));
- 大小比较
LocalDate tomorrow = LocalDate.of(2018, 4, 2);
System.out.println("2018-04-02是未来的时间吗?" + tommorow.isAfter(today));
LocalDate yesterday = today.minus(1, DAYS);
System.out.println("2018-03-31是过去的时间吗?" + yesterday.isBefore(today));
- 日期增加/减少
- 加小时
LocalTime time = LocalTime.now();
LocalTime newTime = time.plusHours(2); // 加2个小时
System.out.println("两个小时后是 : " + newTime);
- 加一周
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
System.out.println("一星期后 : " + nextWeek);
- 加一年
today.minus(1, ChronoUnit.YEARS);
- 获取时区
ZoneId zId = ZoneId.of("GMT+8");
LocalDateTime localtDateAndTime = LocalDateTime.now();
ZonedDateTime bj = ZonedDateTime.of(localtDateAndTime, zId );
- 是否是闰年
System.out.print("今年2019是闰年?" + today.isLeapYear());
- 两个日期直接有多少天和月
LocalDate day = LocalDate.of(2018, Month.APRIL, 1);
LocalDate today = LocalDate.now();
Period period = Period.between(day , today);
System.out.println("2018年4月1日距离今天过去了多少个月: " + period.getMonths());
- 时区偏移量的日期时间
LocalDateTime datetime = LocalDateTime.of(2018, Month.JANUARY, 14, 19, 30);
ZoneOffset offset = ZoneOffset.of("+05:30");
// 给机器看的
OffsetDateTime date = OffsetDateTime.of(datetime, offset);
System.out.println("带时区的日期和时间 : " + date);
// 这个是格式化之后给人看的
ZoneDateTime date = ZoneDateTime.of(datetime, offset);