一、Lambda表達式
Lambda表達式(->):Lambda允許把函數作為一個方法的參數(函數作為參數傳遞到方法中)。
->
将Lambda拆分為兩部分。
- 左側:參數清單。
- 右側:執行功能。
文法規則:
-
無參數,無傳回值
()-> System.out.println(“Hello Lambda!”)
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"匿名内實作多線程!!!");
}
}).start();
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"Lambad内實作多線程!!!");
}).start();
-
有一個參數,并且無傳回值
(x)-> System.out.println(x)
Consumer<String> consumer =(x)->System.out.println(x);
consumer.accept("你好");
-
若隻有一個參數,小括号可以省略不寫
x-> System.out.println(x)
Consumer<String> consumer =x->System.out.println(x);
consumer.accept("你好");
- 有兩個以上的參數,有傳回值,并且 Lambda體中有多條語句
Comparator<Integer> cm =(x,y)->{
System.out.println("函數式接口");
return Integer.compare(x,y);
};
- 若 Lambda體中隻有一條語句, return和大括号都可以省略不寫
Lambda表達式的參數清單的資料類型可以省略不寫,編譯器通過上下文推斷出,資料類型,即“類型推斷”
(Integer x, Integer y)-> Integer. compare(x, y)
練習
1.聲明函數式接口處理字元串
package com.zhou;
//代表這是一個函數式接口,隻能有一個抽象方法
@FunctionalInterface
public interface MyFunction {
String getValue (String str);
}
//字元串處理
public String test3(String str,MyFunction my) {
return my.getValue(str);
}
@Test
public void test4() {
//轉大寫
String ss = test3("abcdefg", (str) -> str.toUpperCase());
//截取
String ss1 = test3("abcdefg", (str) -> str.substring(1,4));
System.out.println(ss);
System.out.println(ss1);
}
2.聲明一個帶兩個泛型的函數式接口,泛型類型為<T, R> T為參數,R為傳回值,并計算相加
package com.zhou;
public interface MyFunctionTwo <T,R>{
R getValue(T t1,T t2);
}
public void test5(Long l1,Long l2,MyFunctionTwo<Long,Long> my) {
System.out.println(my.getValue(l1,l2));
}
@Test
public void test6() {
test5(100L,200L,(x,y)->x+y);
}
二、Java8内置四大函數式接口
- 消費型接口
Consumer<T>
void accept(T t)
//消費型接口
@Test
public void test1 () {
shop(200,x->System.out.println("消費"+x+"元"));
}
public void shop (double money, Consumer<Double> t){
t.accept(money);
}
- 供給型接口
Supplier<Integer>
T get();
//供給型接口
//産生整數放入到集合
public List<Integer> getNumList (Integer num, Supplier<Integer> sp){
List<Integer> list = new ArrayList<>();
for (int i = 0; i <num ; i++) {
Integer ss = sp.get();
list.add(ss);
}
return list;
}
- 函數型接口
Function<T,R>
R apply(T t);
//函數型接口
//處理字元串
public String strHandler(String str, Function<String,String> fun){
return fun.apply(str);
}
@Test
public void test3 () {
String str = strHandler("ABCDEFG", String::toLowerCase);
String s = strHandler("\t\t\t hello ", String::trim);
System.out.println(str);
System.out.println(s);
}
- 斷言型接口
Predicate<T t>
Boolean test(T t);
//斷言型接口
//将滿足條件的字元串放入集合
public List<String> getStr(List<String> str, Predicate<String> prc) {
ArrayList<String> list = new ArrayList<>();
for (String s : str) {
if(prc.test(s)){
list.add(s);
}
}
return list;
}
@Test
public void test4 () {
List<String> strs = Arrays.asList("張三","王麻子","李四","王五");
List<String> str = getStr(strs, x -> x.length()>2);
str.forEach(System.out::println);
}
三、方法引用與構造器引用
3.1、方法引用
方法引用:方法引用提供了非常有用的文法,可以直接引用已有Java類或對象(執行個體)的方法或構造器。與lambda聯合使用,方法引用可以使語言的構造更緊湊簡潔,減少備援代碼。
注意:
Lambda 體中調用方法的參數清單與傳回值類型,要與函數式接口中抽象方法的函數清單和傳回值類型保持一緻!
若Lambda 參數清單中的第一參數是執行個體方法的調用者,而第二個參數是執行個體方法的參數時,可以使用ClassName : method!
主要有三種格式
- 對象 ::執行個體方法名
- 類 ::靜态方法名
- 類::實力方法名
//對象::執行個體方法
@Test
public void test1 () {
Object obj = new Object();
Supplier<Object> sp =obj::getClass;
Object o = sp.get();
System.out.println(o);
}
//靜态方法::執行個體方法
@Test
public void test2 () {
Comparator<Integer> compare = Integer::compare;
int compare1 = compare.compare(100, 20);
System.out.println(compare1);
}
//類::執行個體方法名
@Test
public void test3 () {
BiPredicate<String,String> ss = String::equals;
boolean test = ss.test("ss", "ss");
System.out.println(test);
}
3.2、構造器引用
注意:需要調用的構造器的參數清單要與函數式接口中抽象方法的參數清單保持一緻!│
//構造器引用
@Test
public void test4 () {
Function<Integer,User> fun =User::new;
User us = fun.apply(111111);
System.out.println(us);
Function<Integer,String[]> fc = String[]::new;
String[] str = fc.apply(22);
System.out.println(str.length);
}
四、Stream API
Stream API:新添加的Stream API(java.util.stream) 把真正的函數式程式設計風格引入到Java中。
Stream操作主要有以下三個步驟:
- 建立Stream
從一個資料源,如集合、數組中擷取流。
- 中間操作
一個操作的中間鍊,對資料源的資料進行操作。
- 終止操作
一個終止操作,執行中間操作鍊,并産生結果。
4.1、建立流
- 建立Stream流的四種方式
- 通過Collection集合提供的stream()方法、和paralleStram()
- 通過ArrayList中的stream()方法。
- 通過Stream的靜态of方法()。
- 建立無限流
@Test
public void test1(){
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
System.out.println(stream);
}
@Test
public void test2(){
int [] arr={1,2,3,4};
IntStream stream = Arrays.stream(arr);
}
@Test
public void test3(){
Stream<String> zs = Stream.of("zs", "ls", "ww");
zs.forEach(System.out::println);
}
@Test
public void test4(){
Stream<Integer> num = Stream.iterate(1, (x) -> x+2);
num.limit(5).forEach(System.out::println);
}
4.2、中間操作
4.2.1、過濾與切片
filter:接受Lambda從流中排除某些元素。
limit:截斷流,使其元素不超過指定數量。
skip:跳過元素,傳回一個人掉了前n個的流。
distinct:過濾,通過流的equals和hashcode去重元素。
@Test
public void test5 () {
List<Integer> list = Arrays.asList(21,20,50,28,60,60,50);
//得到流,判斷集合裡面值不超過50的人
list.stream().filter((x)->x>=50)
//跳過前面一個資料取後面一個資料
.skip(1)
//隻顯示1條滿足條件的資料
.limit(2)
//去除
.distinct()
//終止操作
.forEach(System.out::println);
}
4.2.2、映射
map:接收Lambda表達式,将元素轉換成其他形式或提取資訊。接收一個函數作為參數,該函數會被應用到每個元素上,并将其映射成一個新的元素。
flatMap接收一個函數作為參數,該函數會被應用到每個元素上,并将其映射成一個新的元素。
@Test
public void test6 () {
List<String> list = Arrays.asList("aaa","bbb","ccc");
//map接收到Stream的時候會把Stream放入到一個新的Stream最後傳回一個包含多個Stream的Stream
list.stream().map(String::toUpperCase).forEach(System.out::println);
//flatMap會将接受到的Stream的元素放入到一個新的Stream最後傳回一個包含多個Value的Stream
list.stream().flatMap(Streams::getStr).forEach(System.out::println);
}
public static Stream<Character> getStr(String str){
List<Character> list = new ArrayList<>();
for (Character s : str.toCharArray()) {
list.add(s);
}
return list.stream();
}
4.2.3、排序
排序分為自然排序和定制排序。
sorted()–自然排序(Comparable)。
sorted(Comparator com)–定制排序(Comparator)。
package com.zhou;
public class User {
private Integer id;
private String name;
private Integer age;
public User() {
}
public User(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
@Test
public void test7 () {
List<User> userList = Arrays.asList(
new User(1,"李四",20),
new User(2,"王麻子",18),
new User(3,"張三",20)
);
//sorted()--自然排序(Comparable)
// num.stream().sorted().forEach(System.out::println);
//sorted(Comparator com)--定制排序(Comparator)
userList.stream().sorted((e1,e2)->{
//年齡相等按照姓名排序,否則按照年齡進行升序排序
if(e1.getAge()==e2.getAge()){
return e1.getName().compareTo(e2.getName());
}else{
return e1.getAge().compareTo(e2.getAge());
}
}).forEach(System.out::println);
}
4.3、終止操作
Stream的終止操作有查找和比對、歸約和收集。
4.3.1、查詢和比對
- allMatch–檢查是否比對所有元素
- anyMatch–檢查是否至少比對一個元素
- noneMatch–檢查是否沒有比對所有元素
- findFirst–傳回第一個元素
- findAny–傳回目前流中的任意元素
- count–傳回流中元素的總個數
- max–傳回流中最大值
- min–傳回流中最小值
package com.zhou;
public class User {
private Integer id;
private String name;
private Integer age;
public User() {
}
public User(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
/**
* 查找或比對
*/
@Test
public void test8 () {
List<User> userList = Arrays.asList(
new User(1,"李四",20),
new User(2,"王麻子",18),
new User(3,"張三",21)
);
//查詢是否都是成年人
boolean b = userList.stream().allMatch(x -> x.getAge()>=18);
System.out.println(b);
//查詢至少有叫張三的這個人
boolean name = userList.stream().anyMatch(x -> x.getName().equals("張三"));
System.out.println(name);
//檢查沒有叫張三的這個人
boolean names = userList.stream().noneMatch(x -> x.getName().equals("迪迦奧特曼"));
System.out.println(names);
//傳回第一條資料
Optional<User> first = userList.stream().findFirst();
System.out.println(first);
//統計元素的個數
long count = userList.stream().count();
System.out.println("元素的個數:"+count);
//年齡最大值人的資訊
Optional<User> max = userList.stream().max((x,y)->x.getAge().compareTo(y.getAge()));
System.out.println("最大值:"+max);
//年齡最小值人的資訊
Optional<User> min = userList.stream().min((x, y) -> x.getAge().compareTo(y.getAge()));
System.out.println("最小值:"+min);
}
4.3.2、歸約
- 規約就是将流中的元素反複結合起來得到一個值。
Optional<T> reduce(BinaryOperator<T> accumulator);
T reduce(T identity, BinaryOperator<T> accumulator);
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
@Test
public void test9() {
List<Integer> list = Arrays.asList(10, 20, 30, 40, 50);
//0為起始值代表集合中的第一個元素,每次取出一個值都會把值放y裡面進行相加
//第一種寫法
Integer reduce = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(reduce);
//第二種寫法
Optional<Integer> reduce1 = list.stream().reduce(Integer::sum);
System.out.println(reduce1.get());
}
4.3.3、收集
将流轉換為其他形式,接收一個Collector接口實作 ,用于給Stream中彙總的方法。
Optional<T> reduce(BinaryOperator<T> accumulator);
T reduce(T identity, BinaryOperator<T> accumulator);
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
List<User> userList = Arrays.asList(
new User(1,"李四",20),
new User(2,"王麻子",18),
new User(3,"張三",21),
new User(3,"張三",21)
);
//将姓名收集到list集合中
List<String> collect = userList.stream().map(User::getName).collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println("-----------");
//将姓名收集到set集合中
Set<String> collects = userList.stream().map(User::getName).collect(Collectors.toSet());
collects.forEach(System.out::println);
//将姓名保收集到其他集合中
System.out.println("-----------");
LinkedHashSet<String> collect1 = userList.stream().map(User::getName)
.collect(Collectors.toCollection(LinkedHashSet::new));
collect1.forEach(System.out::println);
//使用收集進行規約操作
Double collect2 = userList.stream().collect(Collectors.averagingDouble(x -> (int) x.getAge()));
System.out.println("平均年齡:"+collect2);
//使用收集進行分組
Map<Integer, List<User>> collect3 = userList.stream().collect(Collectors.groupingBy(User::getAge));
System.out.println(collect3);
//多級分組
Map<Integer, Map<Object, List<User>>> collect4 = userList.stream()
//如果年齡大于18就是成年人否則就是未成年
.collect(Collectors.groupingBy(User::getAge, Collectors.groupingBy((x) -> {
if (((User) x).getAge() >= 18) {
return "成年人";
}else {
return "未成年";
}
})));
System.out.println(collect4);
//連接配接字元串
String collect5 = userList.stream().map(User::getName).collect(Collectors.joining(","));
System.out.println(collect5);
五、并行流和串行流
- 并行流就是把一個内容分成多個資料塊,并用不同的線程分别處理每個資料塊的流。
- Stream API可以聲明性地通過
與parallel()
在并行流與順序流之間進行切換。sequential()
- Fork/Join架構:就是在必要的情況下,将一個大任務,進行拆分(fork)成若幹個小任務(拆到不可再拆時),再将一個個的小任務運算的結果進行join彙總。
Fork/Join架構與傳統線程池的差別
采用工作竊取模式(work-stealing)
當執行新的任務時,它可以将其拆分成更小的任務執行,并将小任務加到線程隊列中,然後再從一個随機線程的隊列中偷一個并把它放在自己的隊列中。
相對于一般的線程池實作,fork/join架構的優勢展現在對其中包含的任務的處理方式上。在一般線程池中,如果一個線程正在執行的任務由于某些原因無法繼續運作,那麼該線程會處于等待狀态。
而在fork/join架構實作中,如果某個子問題由于等待另外一個子問題的完成而無法繼續運作,那麼處理該子問題的線程會主動尋找其他尚未運作的子問題來執行,這種方式減少了線程的等待時間,提高了性能。
package com.zhou;
import java.util.concurrent.RecursiveTask;
public class ForkJoinCalculate extends RecursiveTask<Long> {
private long start;
private long end;
//臨界值
private static final long THRESHOLD=10000L;
public ForkJoinCalculate(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long length = end-start;
if(length<THRESHOLD){
long sum =0;
for (long i = start; i <end ; i++) {
sum +=i;
}
return sum;
}else {
long middle = (start+end)/2;
ForkJoinCalculate left = new ForkJoinCalculate(start,middle);
left.fork();//拆分子任務,同時壓入線程隊列
ForkJoinCalculate right = new ForkJoinCalculate(middle+1,end);
right.fork();
return left.join() + right.join();
}
}
}
@Test
public void test11(){
Instant start = Instant.now();
ForkJoinPool fo = new ForkJoinPool();
ForkJoinCalculate ff = new ForkJoinCalculate(0,10000000000L);
Long invoke = fo.invoke(ff);
System.out.println(invoke);
Instant end = Instant.now();
System.out.println("耗時:"+Duration.between(start,end).getSeconds()+"秒");
}
結果:-5345475101129947011
耗時:2秒
/**
* 使用普通for循環方式來計算,比較二者時間
*/
@Test
public void test13(){
long startTime = System.currentTimeMillis();
long sum = 0L;
for (long i = 0 ; i <= 10000000000L ; i ++ ){
sum += i;
}
System.out.println(sum);
long endTime = System.currentTimeMillis();
System.out.println("消耗時間:" + (endTime - startTime)/1000+"秒");
}
結果:-5340232216128654848
消耗時間:3秒
//計算1000億資料累加
@Test
public void test12 () {
Instant start = Instant.now();
long reduce = LongStream.rangeClosed(0, 100000000000L).parallel().reduce(0, Long::sum);
System.out.println(reduce);
Instant end = Instant.now();
System.out.println("耗時:"+Duration.between(start,end).getSeconds()+"秒");
}
結果:932356074711512064
耗時:15秒
六、Otional類
Optional類:Optional 類已經成為 Java 8 類庫的一部分,用來解決空指針異常。
package com.zhou;
public class User {
private Integer id;
private String name;
private Integer age;
public User() {
}
public User(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
@Test
public void test () {
//建立一個Optional執行個體,參數為null會報空指針異常
Optional<User> user = Optional.of(new User());
User user1 = user.get();
System.out.println(user1);
}
@Test
public void test1 () {
//允許傳遞為 null 參數
Optional<Object> o = Optional.ofNullable(null);
//判斷參數是否存在
// if(o.isPresent()){
// System.out.println(o.get());
// }
//如果調用對象包含值傳回值,否則傳回擷取的值
User user= (User) o.orElseGet(()->new User());
System.out.println(user);
//值存在傳回,否則傳回預設值
User user1= (User) o.orElse(new User(1,"李四",22));
System.out.println(user1);
}
//如果有值進行處理,并傳回處理後的OPtional否則傳回Optional.empty()
@Test
public void test2 () {
Optional<User> o = Optional.ofNullable(new User(1,"zs",22));
Optional<String> s = o.map(x -> x.getName());
System.out.println(s.get());
Optional<Integer> s1 = o.flatMap(x -> Optional.of(x.getAge()));
System.out.println(s1.get());
}
七、預設方法和靜态方法
預設方法:預設方法就是一個在接口裡面有了一個實作的方法。
package com.zhou;
public interface MyInterface {
//預設方法被default修飾
default String getStr () {
return "你好啊";
}
//靜态方法
static void show () {
System.out.println("接口中的靜态方法..........");
}
}
package com.zhou;
public class TestMyInterface implements MyInterface{
public static void main(String[] args) {
//通過接口執行個體化子類
//接口方法預設類優先原則:
//如果接口定義了預設方法.另一個父類或者接口定義了同名方法時,選擇父類中的方法(父類方法被實作,接口中相同名稱和參數的方法會被忽略)
//接口沖突。如果一個父接口和其他的接口具有相同的方法名稱和參數必須使用覆寫來解決沖突.
MyInterface my = new TestMyInterface();
String str = my.getStr();
System.out.println(str);
MyInterface.show();
}
}
八、新的時間API
Date Time API:加強對日期與時間的處理,java.time包下的所有類都是不可變類型而且線程安全。
-
:不包含時間的日期,比如LocalDate
。可以用來存儲生日,周年紀念日,入職日期等。2019-10-14
@Test
public void localDate() {
//擷取目前年月日
LocalDate today = LocalDate.now();
System.out.println("目前年月日:" + today);
// 擷取年的兩種方式
int thisYear = today.getYear();
int thisYearAnother = today.get(ChronoField.YEAR);
System.out.println("今年是" + thisYear + "年");
System.out.println("今年是" + thisYearAnother + "年");
// 擷取月
Month thisMonth = today.getMonth();
System.out.println(thisMonth.toString());
// 這是今年的第幾個月(兩種寫法)
int monthOfYear = today.getMonthValue();
// int monthOfYear = today.get(ChronoField.MONTH_OF_YEAR);
System.out.println("這個月是今年的第" + monthOfYear + "個月");
// 月份的天數
int length = today.lengthOfMonth();
System.out.println("這個月有" + length + "天");
// 擷取日的兩種方式
int thisDay = today.getDayOfMonth();
int thisDayAnother = today.get(ChronoField.DAY_OF_MONTH);
System.out.println("今天是這個月的第" + thisDay + "天");
System.out.println("今天是這個月的第" + thisDayAnother + "天");
// 擷取星期
DayOfWeek thisDayOfWeek = today.getDayOfWeek();
System.out.println(thisDayOfWeek.toString());
// 今天是這周的第幾天
int dayOfWeek = today.get(ChronoField.DAY_OF_WEEK);
System.out.println("今天是這周的第" + dayOfWeek + "天");
// 是否為閏年
boolean leapYear = today.isLeapYear();
System.out.println("今年是閏年:" + leapYear);
//構造指定的年月日
LocalDate anotherDay = LocalDate.of(2008, 8, 8);
System.out.println("指定年月日:" + anotherDay);
}
-
:與LocalTime
想對照,它是不包含日期的時間。LocalDate
@Test
public void localTime() {
// 擷取目前時間
LocalTime nowTime = LocalTime.now();
System.out.println("目前時間:" + nowTime);
//擷取小時的兩種方式
int hour = nowTime.getHour();
int thisHour = nowTime.get(ChronoField.HOUR_OF_DAY);
System.out.println("目前時:" + hour);
System.out.println("目前時:" + thisHour);
//擷取分的兩種方式
int minute = nowTime.getMinute();
int thisMinute = nowTime.get(ChronoField.MINUTE_OF_HOUR);
System.out.println("目前分:" + minute);
System.out.println("目前分:" + thisMinute);
//擷取秒的兩種方式
int second = nowTime.getSecond();
int thisSecond = nowTime.get(ChronoField.SECOND_OF_MINUTE);
System.out.println("目前秒:" + second);
System.out.println("目前秒:" + thisSecond);
// 構造指定時間(最多可到納秒)
LocalTime anotherTime = LocalTime.of(20, 8, 8);
System.out.println("構造指定時間:" + anotherTime);
}
-
:包含了日期及時間,沒有偏移資訊(時區)。LocalDateTime
// 目前日期和時間
LocalDateTime today = LocalDateTime.now();
System.out.println("現在是:" + today);
// 建立指定日期和時間
LocalDateTime anotherDay = LocalDateTime.of(2008, Month.AUGUST, 8, 8, 8, 8);
System.out.println("建立的指定時間是:" + anotherDay);
// 拼接日期和時間
// 使用目前日期,指定時間生成的 LocalDateTime
LocalDateTime thisTime = LocalTime.now().atDate(LocalDate.of(2008, 8, 8));
System.out.println("拼接的日期是:" + thisTime);
// 使用目前日期,指定時間生成的 LocalDateTime
LocalDateTime thisDay = LocalDate.now().atTime(LocalTime.of(12, 24, 12));
System.out.println("拼接的日期是:" + thisDay);
// 指定日期和時間生成 LocalDateTime
LocalDateTime thisDayAndTime = LocalDateTime.of(LocalDate.of(2008, 8, 8), LocalTime.of(12, 24, 12));
System.out.println("拼接的日期是:" + thisDayAndTime);
// 擷取LocalDate
LocalDate todayDate = today.toLocalDate();
System.out.println("今天日期是:" + todayDate);
// 擷取LocalTime
LocalTime todayTime = today.toLocalTime();
System.out.println("現在時間是:" + todayTime);
-
:包含時區的完整的日期時間,偏移量是以ZonedDateTime
/格林威治時間為基準的。UTC
public class InstantDemo {
public static void main(String[] args) {
// 建立Instant對象
Instant instant = Instant.now();
// 通過ofEpochSecond方法建立(第一個參數表示秒,第二個參數表示納秒)
Instant another = Instant.ofEpochSecond(365 * 24 * 60, 100);
// 擷取到秒數
long currentSecond = instant.getEpochSecond();
System.out.println("擷取到秒數:" + currentSecond);
// 擷取到毫秒數
long currentMilli = instant.toEpochMilli();
System.out.println("擷取到毫秒數:" + currentMilli);
}
}
-
:時間戳,與Instant
類似。System.currentTimeMillis()
@Test
public void Instant() {
// 建立Instant對象
Instant instant = Instant.now();
// 通過ofEpochSecond方法建立(第一個參數表示秒,第二個參數表示納秒)
Instant another = Instant.ofEpochSecond(365 * 24 * 60, 100);
// 擷取到秒數
long currentSecond = instant.getEpochSecond();
System.out.println("擷取到秒數:" + currentSecond);
// 擷取到毫秒數
long currentMilli = instant.toEpochMilli();
System.out.println("擷取到毫秒數:" + currentMilli);
}
-
:表示一個時間段。Duration
@Test
public void duration() {
LocalDateTime from = LocalDateTime.now();
LocalDateTime to = LocalDateTime.now().plusDays(1);
// 通過between()方法建立
Duration duration = Duration.between(from, to);
// 通過of()方法建立,該方法參數為時間段長度和時間機關。
// 7天
Duration duration1 = Duration.of(7, ChronoUnit.DAYS);
// 60秒
Duration duration2 = Duration.of(60, ChronoUnit.SECONDS);
}
-
:用來表示以年月日來衡量一個時間段。Period
@Test
public static void period() {
// 通過of方法
Period period = Period.of(2012, 12, 24);
// 通過between方法
Period period1 = Period.between(LocalDate.now(), LocalDate.of(2020,12,31));
}
-
:新的日期解析格式化類。DateTimeFormatter
@Test
public void format() {
LocalDate today = LocalDate.now();
// 兩種預設格式化時間方式
String todayStr1 = today.format(DateTimeFormatter.BASIC_ISO_DATE);
String todayStr2 = today.format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println("格式化時間:" + todayStr1);
System.out.println("格式化時間:" + todayStr2);
//自定義格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String todayStr3 = today.format(dateTimeFormatter);
System.out.println("自定義格式化時間:" + todayStr3);
}