Java8新的日期时间Api、Lambda表达式和Stream流的使用

JDK8新特性

1 日期、时间

1.1 JDK8之前传统的日期、时间

设计不合理,使用不方便;都是可变时间,修改后会丢失最初的时间信息;线程不安全;只能精确到毫秒

  • Date
  • SimpleDateFormat
  • Calendar
1.1.1 Date
构造器说明
public Date()创建一个Date对象,代表的是系统当前此刻日期时间
public Date(long time)把时间毫秒值转换成Date日期对象
常见方法说明
public long getTime()返回从1970年1月1日 00:00:00走到此刻的总的毫秒数
public void setTime(long time)设置日期对象的时间为当前时间毫秒值对应的时间
1.1.2 SimpleDateFormat
构造器说明
public SimpleDateFormat(String pattern)创建简单日期格式化对象,并封装时间的格式
常见方法说明
public final String format(Date date)将日期格式化成日期/时间字符串
public final String format(Object time)将时间毫秒值格式化成日期/时间字符串
public Date parse(String source)把字符串时间解析成日期对象(注意:待转换的字符串时间格式要和SimpleDateFormat对象指定的时间格式保持一致)
常用日期时间字符串格式格式化后的字符串备注
“yyyy.MM.dd HH:mm:ss”“2024.06.01 17:02:11”"HH"表示24小时制
“yyyy.MM.dd hh:mm:ss”“2024.06.01 5:02:11”"hh"表示12小时制
“yyyy年MM月dd日 HH时mm分ss秒”“2024年06月01日 17时02分11秒”"HH"表示24小时制

其他时间格式符号:EEE 表示星期几;a 表示上午/下午;S(大写) 表示毫秒;

1.1.3 Calendar

Calendar代表的是系统此刻时间对应的日历
通过Calendar可以单独获取、修改时间中的年,月,日,时,分,秒等

获取Calendar对象的方法:
Calendar rightNow=Calendar.getInstance();

注意:Calendar是可变对象,一旦修改后其对象本身表示的时间将产生变化

常见方法说明
public static Calendar getInstance()获取当前日历对象
public int get(int field)获取日历中的某个信息
public final Date getTime()获取日期对象
public long getTimeInMillis()获取时间毫秒值
public void set(int field ,int value)修改日历的某个信息
public void add(int field ,int amount)为某个信息增加/减少指定的值

1.2 JDK8新增的日期、时间

设计更合理,功能丰富,使用方便;都是不可变对象,修改后会返回新的时间对象,不会丢失最开始的时间信息;线程安全;能精确到毫秒、纳秒。

  • LocalDate(年,月,日,星期)、LocalTime(时,分,秒,纳秒)、LocalDateTime(年,月,日,星期, 时,分,秒,纳秒)
  • ZoneId(时区)、ZoneDateTime(带时区的时间)
  • Instant(时间戳/时间线)
  • DateTimeFormatter(勇于时间的格式化和解析)
  • Duration(时间间隔,时、分、秒,纳秒)、Period(时间间隔年,月,日)

代替Calendar的类

  • LocalDate
  • LocalTime
  • LocalDateTime
  • ZoneId
  • ZoneDateTime

代替Date的类

  • Instant

代替SimpleDateFormat的类

  • DateTimeFormatter

其他补充

  • Period
  • Duration
1.2.1 LocalDate,LocalTime,LocalDateTime
方法名实例
public static Xxxx now()获取系统当前时间对应的该对象LocalDate ld = LocalDate.now()
LocalTime lt = LocalTime.now()
LocalDateTime ldt = LocalDateTime.now()
public static Xxxx of(…)获取指定时间的对象LocalDate ld = LocalDate.of(2099,11,11)
LocalTime lt = LocalTime.of(9,8,59)
LocalDateTime ldt = LocalDateTime.of(2099,11,11,9,8,59)
LocalDate常用方法作用
int getYear()获取年份
int getMonthValue()获取月份(1-12)
int getDayOfMonth()获取日(几号)
int getDayOfYear()一年中的第几天
int getDayOfWeek().getValue()星期几
LocalDate withYear(int year)修改年份
LocalDate withMonth(int month)修改月份
LocalDate withDayOfMonth(int day)修改日(几号)
LocalDate withDayOfYear(int day)修改天数(一年中的第几天)
LocalDate plusYears(int year)把年份加多少
LocalDate plusMonths(int month)把月份加多少
LocalDate plusDays(int day)把日(几号)加多少
LocalDate plusWeeks(int week)把星期几加多少
LocalDate minusYears(int year)把年份减多少
LocalDate minusMonths(int month)把月份减多少
LocalDate minusDays(int day)把日(几号)减多少
LocalDate minusWeeks(int week)把星期几减多少
public static LocalDate of(int year,int month,int dayOfMonth)获取指定日期的LocalDate对象
boolean equals(LocalDate localDate)判断两个LocalDate对象是否相等
boolean isBefore(LocalDate localDate)某个日期是否在localDate之前
boolean isAfter(LocalDate localDate)某个日期是否在localDate之后

LocalTime和LocalDate常用方法形式相同

LocalTime常用方法作用
int getHour()
int getMinute()
int getSecond()
int getNano()纳秒
LocalDateTime特有方法作用
public LocalDate toLocalDate()把LocalDateTime对象转换为LocalDate对象
public LocalTime toLocalTime()把LocalDateTime对象转换为LocalTime对象
public static LocalDateTime of(LocalDate date,LocalTime time)把LocalDate和LocalTime对象合并为一个LocalDateTime对象
1.2.2 ZoneId(时区)、ZoneDateTime(带时区的时间)
ZoneId常用方法作用
public static ZoneId systemDefault()获取系统默认的时区
public static Set getAvailableZoneIds()获取Java支持的全部时区Id
public static ZoneId of(String zoneId)把某个时区Id封装成ZoneId对象
ZoneDateTime常用方法作用
public static ZoneDateTime now(ZoneId zone)获取某个时区的ZoneDateTime对象
public static ZoneDateTime now()获取系统默认时区的ZoneDateTime对象

ZoneDateTime其他功能用法和LocalDateTime几乎全部一样

1.2.3 Instant

Instant对象由两部分组成:从1970-01-01 00:00:00 开始走到此刻的总秒数+不够1秒的纳秒数

作用:可以用来记录代码的执行时间,或用于记录用户操作某个事件的时间点

Instant常用方法作用
public static Instant now()获取当前的Instant对象
public long getEpochSecond()获取从1970-01-01 00:00:00开始记录的秒数
public int getNano()获取不够一秒的纳秒数
plusMillis(),plusSeconds(),plusNanos()增加时间系列的方法
minusMillis(),minusSeconds(),minusNanos()减少时间系列的方法
equals(),isBefore(),isAfter()判断时间系列的方法
1.2.4 DateTimeFormatter

线程安全

DateTimeFormatter常用方法作用
public static DateTimeFormatter ofPattern(时间格式)获取格式化器对象
public String format(时间对象)格式化时间

LocalDateTime提供的格式化、解析时间的方法

方法名作用
public String format(DateTimeFormatter formatter)格式化时间
public static LocalDateTime parse(CharSequence text,DateTimeFormatter formatter)解析时间
DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now=LocalDateTime.now();

//使用DateTimeFormatter格式化时间
String rs=formatter.format(now);//正向格式化

//使用LocalDateTime提供的格式化方法来格式化
String rs2=now.format(formatter);//反向格式化

//解析时间:解析时间一般使用LocalDateTime提供的解析方法来解析
String dateStr="2024-6-1 22:58:23";
LocalDateTime ldt=LocalDateTime.parse(dateStr,formatter);
1.2.5 Duration、Period

Period(一段时间):

  • 可以用来计算两个LocalDate对象相差的年数,月数,天数
Period常用方法作用
public static Period between(LocalDate start,LocalDate end)传入两个LocalDate日期对象,得到Period对象
public int getYears()计算隔几年,并返回
public int getMonths()计算隔几月,并返回
public int getDays()计算隔几天,并返回(例如:2024-3-7到2024-6-15返回的天数就是8)

Duration(持续时间):

  • 可以用于计算两个时间对象相差的天数,小时数,分数,秒数,纳秒数
  • 支持LocalTime,LocalDateTime,Instant等时间
Duration常用方法作用
public static Duration between(开始时间对象1,截止时间对象2)传入两个时间对象,得到Duration对象
public long toDays()计算隔多少天,并返回
public long toHours()计算隔多少小时,并返回
public long toMinutes()计算隔多少分钟,并返回
public long toSeconds()计算隔多少秒,并返回
public long toMillis()计算隔多少毫秒,并返回
public long toNanos()计算隔多少纳秒,并返回

2 Lambda表达式

JDK8以上版本可用
作用:简化匿名内部类的代码写法。
使用前提:只能简化函数式接口的匿名内部类
函数式接口: 有且仅有一个抽象方法的接口,使用@FunctionalInterface注解修饰的接口必定是函数式接口

假设有以下一个函数式接口

public Interface A{
    int fun(int a);
}

如果使用常规匿名内部类的形式书写,格式如下:

A a = new A{
    public int fun(int a){
        return a+11;
    }
};

如果使用Lambda表达式形式书写,格式如下:

A a = (int a) -> {
    return a+11;
};

2.1 Lambda表达式的省略写法(进一步简化的写法)

  • 参数类型可以省略不写
  • 如果只有一个参数,参数类型可以省略不写,同时()也可以省略
  • 如果Lambda表达式中的方法体代码只有一行,可以省略大括号不写,同时要省略分号!此时,如果这行代码是return语句,也必须去掉return不写。

所以上边的Lambda表达式可以进一步简化为:

A a = a -> a+11;

3 方法引用

作用:进一步简化Lambda表达式
方法引用的标志性符号为 “::”

3.1 静态方法引用

使用方法:类名::静态方法
使用场景:如果某个Lambda表达式中只是调用一个静态方法,并且前后参数的形式一致,就可以使用静态方法引用
例如:

class CompareByData{
    public static int compareByAge(Student o1,Student o2){
        return o1.getAge() - o2.getAge();
    }
}
//常规Lambda写法
Arrays.sort(students,(o1,o2) -> o1.getAge()-o2.getAge());

//使用CompareByData类的写法
Arrays.sort(students,(o1,o2) -> CompareByData.compareByAge(o1,o2));

//使用静态方法引用后的写法
Arrays.sort(students,CompareByData::compareByAge)

3.2 实例方法的引用

使用方法:对象名::实例方法
使用场景:如果某个Lambda表达式中只是调用一个实例方法,并且前后参数的形式一致,就可以使用实例方法引用

class CompareByData{
    public static int compareByAge(Student o1,Student o2){
        return o1.getAge() - o2.getAge();
    }
    public int compareByAgeDesc(Student o1,Student o2){
        return o2.getAge() - o1.getAge();
    }
}
//常规Lambda写法
Arrays.sort(students,(o1,o2) -> o2.getAge()-o1.getAge());

//使用CompareByData类实例对象的写法
CompareByData compareByData = new CompareByData();
Arrays.sort(students,(o1,o2) -> compareByData.compareByAgeDesc(o1,o2));

//使用实例方法引用后的写法
Arrays.sort(students,compareByData::compareByAgeDesc)

3.3 特定类型的方法引用

使用方法:类型::方法
使用场景:如果某个Lambda表达式中只是调用一个实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该石实例方法入参的,则此时就可以使用特定类型的方法引用

String[] names = {"Abddd","abdcc","Bdacc","Bbcca","dd"};

//要求:忽略首字母大小写进行排序

//常规写法
Arrays.sort(names,new Comparator<String>(){
    @Override
    public int compare(String o1,String o2){
        return o1.compareToIgnoreCase(o2);
    }
});

//使用Lambda表达式的写法
Arrays.sort(names,(o1,o2) -> o1.compareToIgnoreCase(o2));

//使用特定类型的方法引用后的写法
Arrays.sort(names,String::compareToIgnoreCase);

3.4 构造器引用

使用方法:类名::new
使用场景:如果某个Lambda表达式中只是在创建对象,并且前后参数情况一致,就可以使用构造器引用。

class Car{
    private String name;
    private double price;

    public Car(){

    }

    public Car(String name,double price){
        this.name=name;
        this.price=price;
    }

    .....
}

interface CreateCar{
    Car create(String name,double price);
}

//不使用Lambda表达式写法
CreateCar cc = new CreateCar(){
    @Override
    public Car create(String name,double price){
        return new Car(name,price);
    }
}

//使用Lambda表达式写法
CreateCar cc = (name,price) -> new Car(name,price);

//使用构造器引用的写法
CreateCar cc = Car::new;

4 Stream流

可以用来操作集合或者数组的数据
优势:Stream流大量的结合了Lambda的语法风格来编程,提供了一种更强大,更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好。

Stream流的使用步骤:

  1. 从数据源(集合/数组)获取Stream流
  2. 调用流的各种中间方法对数据进行处理,计算
  3. 使用终结方法获取处理结果,遍历、统计、收集到一个新集合中返回

4.1 获取Stream流

获取集合的Stream流
Collection接口提供的方法
default Stream stream() 获取当前集合对象的Stream流

获取数组的Stream流
Arrays类提供的方法:
public static Stream stream(T[] array) 获取当前数组的Stream流
Stream类提供的方法:
public static Stream of(T… values) 获取当前接收数据的Stream流

//获取集合的流
List<String> names=new ArrayList<>();
...
Set<String> set=new HashSet<>();
...
Map<String,Double> map=new HashMap<>();
...

//获取Stream流
Stream<String>stream1= names.stream();
Stream<String>stream2= set.stream();

//因为stream方法是Collection接口提供的所以Map集合没办法直接用,但是可以把Map转换为Set集合后使用stream方法获得Stream流
//获取键集合的流
Set<String> keys=map.keySet();
Stream<String> ks=keys.stream();

//获取值集合的流
Collection<Double> values=map.Values();
Stream<Double> vs=values.stream();

//把键值对作为一个整体,获取这个整体集合的流
Set<Map.Entry<String,Double>> entries=map.entrySet();
Stream<Map.Entry<String,Double>> kvs=entries.stream();

//获取数组的流

String[] names={"1","2","3","4"};

//使用Arrays类提供的方法获取流
Stream<String> stream3=Arrays.stream(names);

//使用Stream类提供的of方法获取流
Stream<String> stream4=Stream.of(names);

4.2 Stream流的中间方法

中间方法是指调用完成之后会返回新的Stream流,可以继续使用(支持链式编程)

Stream提供的常用中间方法说明
Stream< T> filter(Predicate<? super T> predicate)用于对流中的数据进行过滤
Stream< T> sorted()对流中的数据进行生序排序
Stream< T> sorted(Comparator<? super T> comparator)对流中的数据按照指定规则排序
Stream< T> limit(long maxSize)获取前几个元素
Stream< T> skip(long n)跳过前几个元素
Stream< T> distinct()去除流中重复的元素
< R> Stream< R> map(Function<? super T,? extends R>mapper)对元素加工并返回对应的新流(又称为映射方法)
static< T> Stream< T> concat(Stream a,Stream b)合并a和b两个流为一个流

4.3 Stream流的终结方法

终结方法是指调用完成之后,不会返回新Stream了,没法继续使用流了

Stream提供的常用终结方法说明
void forEach(Consumer action)对此流运算后的元素执行遍历
long count()统计此流运算后的元素个数
Optional< T> max(Comparator<? super T> comparator)获取此流运算后的最大值元素,执行完后使用get()方法获取最大值元素
Optional< T> min(Comparator<? super T> comparator)获取此流运算后的最小值元素,执行完后使用get()方法获取最小值元素

收集Stream流:就是把Stream流操作后的结果转回集合或者数组中去返回
Stream流:方便操作集合/数组的手段,集合/数组:才是开发中的目的

注意:流只能收集一次,收集后流就被关闭了

Stream提供的常用终结收集方法说明
R collect(Collector collector)把流处理后的结果收集到一个指定的集合中去(例如:想收集为List集合,则参数为Collectors.toList())
Object[] toArray()把流处理后的结果收集到一个数组中去
Stream<Student> stream1=...;
//把流收集到List集合
List<Student> studentList = stream1.collect(Collectors.toList());

//把流收集到Map集合中
//注意:此方法使用前要先把作为键的数据去重,不然会抛异常
Map<String,Double> map=stream1
.collect(Collectors.toMap(a->a.getName(),a->a.getHeight()));

//把留收集到数组中
Student[] arr=stream1.toArray(len->new Student[len]);
  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值