t03_jdk8

六个小豹發表於2024-03-11

日期-時間

LocalDateTime

/**
 * LocalDateTime
 * 獲取本地日期時間物件:年-月-日T時:分:秒.納秒
 * LocalDateTime.now();獲取當前日期
 * LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond);獲取指定日期
 * 注意:LocalDateTime()修改日期,不會將原有日期修改,會返回一個新的日期物件
 * 注意字首
 * with:直接修改某個資訊
 * plus:將某個資訊新增多少
 * minus:將某個資訊減多少
 * to:轉換為某個日期或這時間物件
 *
 * isAfter():判斷某個時間是否在某一時間之後
 * isBefore():判斷某個時間是否在某一時間之前
 * equals():判斷兩個時間是否相等
 */
@Test
void testLocalDateTime(){
        //獲取本地日期和時間物件:年-月-日T時:分:秒.納秒      2023-07-14T15:21:00.524
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime of = LocalDateTime.of(2000, 06, 16, 8, 15, 22, 232322);
        System.out.println(now);
        System.out.println(now.getDayOfMonth());//某月的第幾天
        System.out.println(now.getMonth());//某月英文
        System.out.println(now.getMonthValue());//某月的數值
        System.out.println(now.getDayOfWeek().getValue());//星期幾
        System.out.println(now.withMonth(10));//修改月份為10,並且返回這個物件
        System.out.println(now.plusMonths(2));//月份新增2
        System.out.println(now.minusYears(3));//年份減少3
        System.out.println("-------");
        System.out.println(now.getHour());//獲取當前小時
        System.out.println(now.getMinute());//獲取當前分鐘
        System.out.println(now.getSecond());//獲取當前秒數
        System.out.println(now.getNano());//獲取當前納秒
        System.out.println(now.withHour(22));//修改小時為22
        System.out.println(now.plusMinutes(12));//分鐘加12
        System.out.println(now.minusSeconds(12));//秒數減12
        System.out.println("-------");
        System.out.println(now);
        System.out.println(of);
        System.out.println("------");
        System.out.println(now.isAfter(of));
        System.out.println(now.isBefore(of));
        System.out.println(now.equals(of));
        LocalDate localDate = now.toLocalDate();//轉換為日期物件
        System.out.println(localDate);
        LocalTime localTime = now.toLocalTime();//轉換為時間物件
        System.out.println(localTime);
}

結果如下:

2023-07-14T15:41:28.009
14
JULY
7
5
2023-10-14T15:41:28.009
2023-09-14T15:41:28.009
2020-07-14T15:41:28.009
-------
15
41
28
9000000
2023-07-14T22:41:28.009
2023-07-14T15:53:28.009
2023-07-14T15:41:16.009
-------
2023-07-14T15:41:28.009
2000-06-16T08:15:22.000232322
------
true
false
false
2023-07-14
15:41:28.009
2023-07-14T15:41:28.009

Process finished with exit code 0

image-20230714154230418

LocalDate

/**
 * LocalDate
 * 獲取本地日期物件:年-月-日
 * LocalDate.now();獲取當前日期
 * LocalDate.of(year,month,dayOfMonth);獲取指定日期
 * 注意:LocalDate()修改日期,不會將原有日期修改,會返回一個新的日期物件
 * 注意字首
 * with:修改某個資訊
 * plus:將某個資訊新增多少
 * minus:將某個資訊減多少
 * isAfter():判斷某個日期是否在某一日期之後
 * isBefore():判斷某個日期是否在某一日期之前
 * equals():判斷兩個日期是否相等
 */
@Test
void testLocalDate(){
    //獲取本地日期物件:年-月-日
    LocalDate now = LocalDate.now();
    System.out.println(now);//2023-07-14
    System.out.println(now.getDayOfMonth());//某月的第幾天
    System.out.println(now.getMonth());//某月英文
    System.out.println(now.getMonthValue());//某月的數值
    System.out.println(now.getDayOfWeek().getValue());//星期幾
    System.out.println(now.withMonth(10));//修改月份為10,並且返回這個物件
    System.out.println(now.plusMonths(2));//月份新增2
    System.out.println(now.minusYears(3));//年份減少3
    System.out.println("-------");
    LocalDate of = LocalDate.of(2000, 5, 27);//獲取指定的日期物件
    System.out.println(of);
    System.out.println(now.isAfter(of));
    System.out.println(now.isBefore(of));
    System.out.println(now.equals(of));
}

結果如下:

image-20230714154345069

LocalTime

/**
 *
 * LocalTime
 * 獲取本地時間物件:時:分:秒.納秒
 * LocalTime.now();獲取當前時間
 * LocalTime.of(int hour, int minute, int second, int nanoOfSecond);獲取指定時間
 * 注意:LocalTime()修改時間,不會將原有時間修改,會返回一個新的時間物件
 * 注意字首
 * with:直接修改某個資訊
 * plus:將某個資訊新增多少
 * minus:將某個資訊減多少
 * isAfter():判斷某個時間是否在某一時間之後
 * isBefore():判斷某個時間是否在某一時間之前
 * equals():判斷兩個時間是否相等
 */
@Test
void testLocalTime(){
    //獲取本地時間物件:時:分:秒.納秒
    LocalTime now = LocalTime.now();
    LocalTime of = LocalTime.of(22, 30, 33, 6666);
    System.out.println(now);//獲取當前時間
    System.out.println(now.getHour());//獲取當前小時
    System.out.println(now.getMinute());//獲取當前分鐘
    System.out.println(now.getSecond());//獲取當前秒數
    System.out.println(now.getNano());//獲取當前納秒
    System.out.println(now.withHour(22));//修改小時為22
    System.out.println(now.plusMinutes(12));//分鐘加12
    System.out.println(now.minusSeconds(12));//秒數減12
    System.out.println("------");
    System.out.println(of);
    System.out.println(now.isAfter(of));//now在of之前?
    System.out.println(now.isBefore(of));//now在of之後?
    System.out.println(now.equals(of));//now和of是否相等
}

結果如下:

image-20230714154405719

ZoneId ZonedDateTime

/**
 * ZoneId ZonedDateTime
 * 時區
 * ZonedDateTime與LocalDateTime中獲取日期時間的方法基本一致
 */
@Test
void testZoneId(){
    ZoneId zoneId = ZoneId.systemDefault();
    System.out.println(zoneId.getId());//獲取當前系統預設時區
    System.out.println(zoneId);//相當與呼叫該toString()方法,在這個方法中又呼叫了getId();
    // System.out.println(ZoneId.getAvailableZoneIds());//獲取Java支援的全部時區Id
    ZoneId zoneId1 = ZoneId.of("America/New_York");//將某個時區id封裝成ZoneId物件
    ZonedDateTime now = ZonedDateTime.now(zoneId);//獲取某個時區的ZonedDateTime物件
    System.out.println(now);
    ZonedDateTime now1 = ZonedDateTime.now(Clock.systemUTC());//世界標準時間
    System.out.println(now1);
    System.out.println(ZonedDateTime.now());//系統預設時區的時間
}

image-20230714190213190

Instant

/**
 * Instant
 * 透過獲取Instant的物件可以拿到此刻的時間,該時間由兩部分組成:從1970-01-01 00:00:00開始走到此刻的總秒數+不夠1秒的納秒數
 *
 * 通常用來做程式碼的效能分析,或者記錄使用者的操作時間點
 * 作用:可以用來記錄程式碼的執行時間,或用於記錄使用者操作的某個事件的時間點
 */
@Test
void testInstant(){
    Instant now = Instant.now();//不可變物件
    System.out.println(now);
    System.out.println(now.getEpochSecond());//獲取總秒數
    System.out.println(now.getNano());//不夠一秒的納秒數
    System.out.println(now.plusMillis(111));//納秒加111
}

image-20230714190252668

DateTimeFormatter

/**
 * DateTimeFormatter
 * 時間格式化器
 */
@Test
void testDateTimeFormatter(){
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");//建立時間格式化器物件
    System.out.println(dateTimeFormatter);
    LocalDateTime now = LocalDateTime.now();//對時間進行格式化
    System.out.println(now);
    System.out.println(dateTimeFormatter.format(now));//dateTimeFormatter物件對時間物件now進行格式化
    System.out.println(now.format(dateTimeFormatter));//now物件使用dateTimeFormatter時間格式化器進行格式化
//    解析時間2000年03月23日 17:14:07
    LocalDateTime parse = LocalDateTime.parse("2000年03月23日 17:14:07", dateTimeFormatter);
    System.out.println(parse);
}

image-20230714190409162

Period

/**
 * Period(一段時期)LocalDate
 * 用於計算兩個LocalDate物件 香腸的年數、月數、天數
 */
@Test
void testPeriod(){
    LocalDate start = LocalDate.of(2000, 1, 1);
    LocalDate end = LocalDate.of(2020, 8, 12);
    LocalDate now = LocalDate.now();
    Period between = Period.between(start, end);
    System.out.println(between);
    System.out.println(between.getYears());//間隔年份
    System.out.println(between.getMonths());//間隔月份
    System.out.println(between.getDays());//間隔天數
    System.out.println();
}

image-20230714190443835

Duration

/**
 * Duration(持續時間)LocalTime、LocalDateTime、Instant
 * 用於計算兩個時間物件相差的天數、小時數、分數、秒數、納秒數;支援LocalTime、LocalDateTime、Instant等時間
 *
 */
@Test
void testDuration(){
    LocalDateTime start = LocalDateTime.of(2000, 06, 16, 8, 15, 22, 232322);
    LocalDateTime end = LocalDateTime.of(2011, 9, 22, 22, 17, 22, 64454);
    Duration between = Duration.between(start, end);
    System.out.println(between);
    System.out.println(between.toDays());//天數
    System.out.println(between.toHours());//小時
    System.out.println(between.toMinutes());//分鐘
    System.out.println(between.getSeconds());
    System.out.println(between.toMillis());//毫秒
    System.out.println(between.toNanos());//納秒
    System.out.println(between.getNano());
}

image-20230714190526436

Arrays(陣列)

int[] arr={2,31,5,88,44,22,66,3};
arr.toString()//返回陣列的內容
int[] ints = Arrays.copyOfRange(arr, 0, arr.length);//複製arr陣列中內容到ints中
int[] ints1 = Arrays.copyOf(arr, 10);//將陣列arr中內容複製到ints1中並指定長度
Arrays.setAll(ints1, new IntUnaryOperator() {//將ints1中的數值擴大兩倍
            @Override
            public int applyAsInt(int operand) {.
                return ints1[operand]*2;
            }
        });

Arrays.sort(arr);//排序,升序
Arrays.setAll(ints1,  operand->ints1[operand]*3);//lambd

Lambda表示式

Lambda表示式
注意:Lambda表示式並不是說能簡化所有的匿名內部類的方法,只能簡化函式式介面的匿名內部類。有且僅有一個抽相關方法的介面成為為函式式介面,
注意:大部分函式式介面,上面會有一個@FunctionalInterface的註解,有該註解的介面就必定是函式式介面
引數型別可以不寫,
如果只有一個引數,引數型別可以省略,同時()也可以省略
如果Lambda表示式中的方法體程式碼只有一行程式碼,可以省略大括號不寫,同時要省略分號!此時,如果這行程式碼是return語句,也必須去掉return不寫
interface Animal{
    public void run();
}
@Test
void test1(){
        Animal animal = new Animal() {
            @Override
            public void run() {
                System.out.println("我是Animal");
            }
        };
        animal.run();
        Animal a =( () -> System.out.println("我是Animal"));//Lambda表示式對上述簡寫的
        a.run();
}
interface TestLa{
    public int test(int a,int b);
}
@Test
void test2(){
    int a=39,b=33;
    TestLa testLa = new TestLa() {//匿名內部類
        @Override
        public int test(int a, int b) {
            return a + b;
        }
    };
    System.out.println(testLa.test(a,b));
    TestLa testLa1= (d,f)->d+f;//lambda表示式
    System.out.println(testLa.test(33, 22));
}

方法引用

靜態方法引用

類名::靜態方法

使用場景

如果某個Lambda表示式裡只呼叫一個靜態方法,並且前後引數的形式一致,就可以使用靜態方法引用!

class CompareByData{
    public static int compareByAge(People o1,People o2){
        return o2.getAge()-o1.getAge();
    }
}
@Test
void test3(){
    People[] p=new People[4];
    p[0] = new People("a", "a", "a", 131);
    p[1] = new People("b", "a", "a", 14);
    p[2] = new People("c", "a", "a", 1153);
    p[3] = new People("d", "a", "a", 1213);
    //根據年齡進行升序排序
    Arrays.sort(p,(o1,o2)->o1.getAge()-o2.getAge());
    // Arrays.sort(p, Comparator.comparingInt(People::getAge));//簡寫
    System.out.println(Arrays.toString(p));
    Arrays.sort(p,CompareByData::compareByAge);//靜態方法引用
    System.out.println(Arrays.toString(p));
}

例項方法引用

物件名::例項方法

使用場景

如果某個Lambda表示式裡只有呼叫一個例項方法,並且前後引數的形式一致,就可以使用例項方法引用。

class CompareByData{
    public static int compareByAge(People o1,People o2){
        return o2.getAge()-o1.getAge();
    }
    public int compareByAgeDesc(People o1,People o2){
        return o1.getAge()-o2.getAge();
    }
}
@Test
void test3(){
    People[] p=new People[4];
    p[0] = new People("a", "a", "a", 131);
    p[1] = new People("b", "a", "a", 14);
    p[2] = new People("c", "a", "a", 1153);
    p[3] = new People("d", "a", "a", 1213);
    //根據年齡進行升序排序
    Arrays.sort(p,(o1,o2)->o1.getAge()-o2.getAge());
    // Arrays.sort(p, Comparator.comparingInt(People::getAge));//簡寫
    System.out.println(Arrays.toString(p));
    Arrays.sort(p,CompareByData::compareByAge);//靜態方法引用
    System.out.println(Arrays.toString(p));
    CompareByData compareByData = new CompareByData();
    //升序
    Arrays.sort(p,compareByData::compareByAgeDesc);//例項方法引用
    System.out.println(Arrays.toString(p));

}

特定型別方法引用

型別::方法

使用場景

如果某個Lambda表示式裡只是呼叫一個例項方法,並且前面引數列表中的第一個引數是作為方法的主調,後面所有引數都是作為該例項方法的入參的,則此時就可以使用特定型別的方法引用。

@Test
void test4(){
    String[] names = {"Alice", "bob", "carlie", "bovid", "Eve", "arank", "Grace", "Henry"};
    //    排序(預設按照首字元編號進行升序排序)
    Arrays.sort(names);
    System.out.println(Arrays.toString(names));//[Alice, Eve, Grace, Henry, arank, bob, bovid, carlie]
    System.out.println();
    //    忽略大小寫
    /*        Arrays.sort(names, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareToIgnoreCase(o2);//忽略大小寫
            }
        });
        Arrays.sort(names,(o1,o2)->o1.compareToIgnoreCase(o2));//簡寫*/
    Arrays.sort(names,String::compareToIgnoreCase);//特定型別方法引用
    System.out.println(Arrays.toString(names));
}

構造器引用

類名::new

使用場景

如果某個Lambda表示式裡只是在建立物件,並且前後引數情況一致,就可以使用構造器引用。

import org.junit.jupiter.api.Test;

public class TestCase {
    @Test
    void test1(){
        Create create = new Create() {//一般引用方式
            @Override
            public People testPeople(String name, int age) {
                return new People(name, age);
            }
        };
        System.out.println(create.testPeople("a",22).toString());
        Create create2 =People::new;//構造器引用
        System.out.println(create.testPeople("b",33).toString());
    }
}
interface Create{
    People testPeople(String name,int age);
}

class People{
    private String name;
    private int age;

    public People() {
    }

    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

stream流

鏈式程式設計

stream()://建立流 map集合先轉換為單列集合再建立流
Stream.of(arr):Stream<T> of(T t)//陣列建立流的方法
Arrays.stream(arr)://陣列建立流的方法
distinct()://避免重複
filter(Predicate<? super T> predicate)://過濾器
map(Function<T, R> mapper)`: 該方法將流中的每個元素透過給定的函式進行對映,生成一個新的流。

forEach(Consumer<? super T> action)://迴圈遍歷-終結操作

詳細

  1. filter(Predicate<T> predicate): 該方法用於過濾流中的元素,只保留滿足給定條件的元素。
  2. map(Function<T, R> mapper): 該方法將流中的每個元素透過給定的函式進行對映,生成一個新的流。
  3. flatMap(Function<T, Stream<R>> mapper): 該方法將流中的每個元素透過給定的函式進行對映,並將結果流扁平化為一個新的流。
  4. distinct(): 該方法用於去除流中的重複元素,保留唯一的元素。
  5. sorted()sorted(Comparator<T> comparator)sorted() 方法用於對流中的元素進行自然排序,要求元素實現 Comparable 介面;sorted(Comparator<T> comparator) 則用於根據給定的比較器對流中的元素進行排序。
  6. limit(long maxSize): 該方法用於截斷流,保留前面指定數量的元素。
  7. skip(long n): 該方法用於跳過流中的前 n 個元素,返回一個新的流。
  8. forEach(Consumer<T> action): 該方法對流中的每個元素執行給定的操作。
  9. collect(Collector<T, A, R> collector): 該方法將流中的元素收集到一個結果容器中,使用給定的收集器。
  10. reduce(BinaryOperator<T> accumulator)reduce(T identity, BinaryOperator<T> accumulator)reduce(BinaryOperator<T> accumulator) 用於將流中的元素逐個進行累積操作;reduce(T identity, BinaryOperator<T> accumulator) 則允許指定一個初始值。
  11. anyMatch(Predicate<T> predicate)allMatch(Predicate<T> predicate)noneMatch(Predicate<T> predicate): 這三個方法分別用於判斷流中是否存在任意滿足、全部滿足或沒有滿足給定條件的元素。
  12. findFirst()findAny()findFirst() 用於返回流中的第一個元素;findAny() 則返回流中的任意一個元素。
  13. count(): 該方法用於返回流中元素的數量。
authors.stream()//匿名內部類形式
        .distinct()
        .filter(new Predicate<Author>() {
            @Override
            public boolean test(Author author) {
                return author.getAge()<18;
            }
        })
        .forEach(new Consumer<Author>() {
            @Override
            public void accept(Author author) {
                System.out.println(author.getName());
            }
        });

authors.stream()//lambda簡寫形式
        .distinct()
        .filter(author -> author.getAge()<18)
        .forEach(author -> System.out.println(author.getName()));

Map集合

/**
 * map集合先轉換為單列集合再建立流
 */
private static void test03() {
    HashMap<String, Integer> map = new HashMap<>();
    map.put("a",15);
    map.put("b",22);
    map.put("c",26);
    Set<Map.Entry<String, Integer>> entries = map.entrySet();//轉換為單列
    Stream<Map.Entry<String, Integer>> stream = entries.stream();//建立流
    stream.filter(new Predicate<Map.Entry<String, Integer>>() {
        @Override
        public boolean test(Map.Entry<String, Integer> stringIntegerEntry) {
            return stringIntegerEntry.getValue()<23;
        }
    }).forEach((ss)-> System.out.println(ss));
}

中間操作

filter

/***
 * filter
 * 獲取年齡小於20的作家年齡和名字
 */
private static void test06() {
    List<Author> authors = getAuthors();
    authors.stream()
            .filter(author -> author.getAge()<20)//查詢年齡小於20的
            .forEach(author -> System.out.println(author.getAge()+"--"+author.getName()));
}

map

map(Function<T, R> mapper): 該方法將流中的每個元素透過給定的函式進行對映,生成一個新的流。

/**
 * map
 * 列印所有作家的姓名
 */
private static void test07() {
    List<Author> authors = getAuthors();
    authors.stream()
            .map(author -> author.getName()+"--"+author.getAge())//轉換為字串返回
            .forEach(a-> System.out.println(a));
}

image-20230716121007768

distinct

distinct(): 該方法用於去除流中的重複元素,保留唯一的元素。

/**
 * distinct 去除重複元素
 *
 */
private static void test08() {
    List<Author> authors = getAuthors();
    authors.stream()
            .distinct()//去除重複元素
            .forEach(author -> System.out.println(author.getName()));
}

image-20230716121404095

sorted

排序

sorted()sorted(Comparator<T> comparator)sorted() 方法用於對流中的元素進行自然排序,要求元素實現 Comparable 介面;sorted(Comparator<T> comparator) 則用於根據給定的比較器對流中的元素進行排序。

/**
 * sorted   排序
 * 對流中的元素按照年齡進行排序,要求不要有重複的元素
 */
private static void test09() {
    List<Author> authors = getAuthors();
    authors.stream()
            .distinct()
            .sorted((a,b)->a.getAge()-b.getAge())//排序,傳入物件a,b,然後透過物件獲取年齡,透過物件獲取年齡相減的順序進行排序,前後一致升序,不一致降序
            .forEach(author -> System.out.println(author.getAge()));
}

image-20230716123844614

limit

limit(long maxSize): 該方法用於截斷流,保留前面指定數量的元素。

/**
 * limit
 * 保留指定數量元素
 */
private static void test10() {
    //獲取前三個姓名
    List<Author> authors = getAuthors();
    authors.stream()
            .limit(3)//獲取前三個姓名
            .forEach(author -> System.out.println(author.getName()));
}

image-20230716123814580

skip

skip(long n): 該方法用於跳過流中的前 n 個元素,返回一個新的流。

/**
 *  skip    跳過幾個元素
 */
private static void test11() {
    List<Author> authors = getAuthors();
    // 跳過年齡最小的
    authors.stream()
            .sorted((a,b)->a.getAge()-b.getAge())//找出從小到大排列
            .skip(1)//跳過第一個
            .forEach(author -> System.out.println(author.getName()+"--"+author.getAge()));
}

flatMap

flatMap(Function<T, Stream<R>> mapper): 該方法將流中的每個元素透過給定的函式進行對映,並將結果流扁平化為一個新的流。

/**
 * flatMap
 * 可以返回多個物件
 */
private static void test12() {
    //列印所有書籍的名字並去重
    List<Author> authors = getAuthors();
    authors.stream()
            .flatMap(author -> author.getBooks().stream())
            .distinct()
            .forEach(a-> System.out.println(a.getName()));
}
/**
 * flatMap
 * 可以返回多個物件
 */
private static void test13() {
    //列印現有資料的所有分類,要求去重,
    List<Author> authors = getAuthors();
    authors.stream()
            .flatMap(author -> author.getBooks().stream())
            .distinct()
            .flatMap(author -> Arrays.stream(author.getCategory().split(",")))
            .distinct()
            .forEach(a-> System.out.println(a));
}

image-20230716140801236

終結操作

forEach

forEach(Consumer<T> action): 該方法對流中的每個元素執行給定的操作。

/**
 * forEach
 * 對流中的每個元素執行給定的操作。
 */
private static void test14() {
    List<Author> authors = getAuthors();
    // 獲取所有作家的姓名
    authors.stream().forEach(author -> System.out.println(author.getName()));
}

image-20230716141515315

count

count(): 該方法用於返回流中元素的數量。

/**
 * count
 * 返回元素中的個數
 */
private static void test15() {
    List<Author> authors = getAuthors();
    // 獲取所有作家的姓名
    long count = authors.stream().count();
    System.out.println(count);
}

image-20230716142642108

collect

collect(Collector<T, A, R> collector): 該方法將流中的元素收集到一個結果容器中,使用給定的收集器。

/**
 * collect
 */
private static void test17() {
    //獲取所有存放所有作者名字的集合
    List<Author> authors = getAuthors();
    List<String> collect = authors.stream()
            .map(author -> author.getName())
            .collect(Collectors.toList());
    System.out.println(collect);
}

image-20230716153230535

/**
 * collect
 */
private static void test18() {
    //獲取所有存放所有作者名字的集合
    List<Author> authors = getAuthors();
    Set<String> collect = authors.stream()
            .map(author -> author.getName())
            .collect(Collectors.toSet());//轉換為set集合
    System.out.println(collect);
}

image-20230716153607079

/**
 * collect
 */
private static void test19() {
    //獲取一個map集合,map的key為作者名,value為List<Book>
    List<Author> authors = getAuthors();
    Map<String, List<Book>> collect = authors.stream()
            .distinct()
            .collect(Collectors.toMap(author -> author.getName(), author -> author.getBooks()));//轉換為map集合
    System.out.println(collect);
}

image-20230716154704287

anyMatch、allMatch、noneMatch

anyMatch(Predicate<T> predicate)allMatch(Predicate<T> predicate)noneMatch(Predicate<T> predicate): 這三個方法分別用於判斷流中是否存在任意滿足、全部滿足或沒有滿足給定條件的元素。

/**
 *anyMatch
 */
private static void test20() {
    //判斷是否有年齡小於20的作家
    List<Author> authors = getAuthors();
    boolean b = authors.stream().anyMatch(author -> author.getAge() < 20);
    System.out.println(b);
}

image-20230716160219523

/**
 *allMatch
 */
private static void test21() {
    //判斷是否有年齡小於20的作家
    List<Author> authors = getAuthors();
    boolean b = authors.stream().allMatch(author -> author.getAge() < 20);
    System.out.println(b);
}

image-20230716160334885

/**
 *noneMatch
 */
private static void test22() {
    //判斷是否有年齡小於20的作家
    List<Author> authors = getAuthors();
    boolean b = authors.stream().noneMatch(author -> author.getAge() < 20);
    System.out.println(b);
}

image-20230716160350674

findAny()

findAny() 則返回流中的任意一個元素。

/**
 * findAny
 */
private static void test23() {
    //獲取任意一個年齡大於20的作家,如果存在就輸出他的名字
    List<Author> authors = getAuthors();
    Optional<Author> any = authors.stream()
            .filter(author -> author.getAge()>90)
            .findAny();
    any.ifPresent(author -> System.out.println(author.getName()));
}

image-20230716184417122

findFirst()

findFirst() 用於返回流中的第一個元素;

/**
 * findFirst
 */
private static void test24() {
    //獲取任意一個年齡大於20的作家,如果存在就輸出他的名字
    List<Author> authors = getAuthors();
    Optional<Author> any = authors.stream()
            .filter(author -> author.getAge()>20)
            .findFirst();
    any.ifPresent(author -> System.out.println(author.getName()));
}

image-20230716184651422

reduce*

歸併

reduce(BinaryOperator<T> accumulator)reduce(T identity, BinaryOperator<T> accumulator)

reduce(BinaryOperator<T> accumulator) :用於將流中的元素逐個進行累積操作;

reduce(T identity, BinaryOperator<T> accumulator) :則允許指定一個初始值。

    /**
     *reduce
     */
    private static void test27() {
        //使用reduce求所有作者中年齡的最小值
        List<Author> authors = getAuthors();
        Integer reduce = authors.stream()
                .map(author -> author.getAge())
                .reduce(Integer.MAX_VALUE, (age1, age2) -> age1 < age2?age1:age2);
        System.out.println("最小值:"+reduce);
    }
    /**
     *reduce
     */
    private static void test26() {
        //使用reduce求所有作者中年齡的最大值
        List<Author> authors = getAuthors();
        Integer reduce = authors.stream()
                .map(author -> author.getAge())
                .reduce(Integer.MIN_VALUE, (age1, age2) -> age1 > age2?age1:age2);
        System.out.println("最大值:"+reduce);
    }

    /**
     *reduce
     */
    private static void test25() {
    //    使用reduce計算所有作者年齡的和
        List<Author> authors = getAuthors();
        Integer reduce = authors.stream()
                .map(author -> author.getAge())
                .reduce(0, (sum, age) -> sum + age);
        System.out.println("和:"+reduce);
    }

image-20230716191522183

/**
 *reduce
 傳入單個引數
 */
private static void test28() {
    //使用reduce求所有作者中年齡的最小值,傳入一個引數計算
    List<Author> authors = getAuthors();
    Optional<Integer> reduce = authors.stream()
            .map(author -> author.getAge())
            .reduce((age1, age2) -> age1 < age2 ? age1 : age2);
    reduce.ifPresent(age-> System.out.println(age));
}

注意事項:

惰性求值1(如果沒有終結操作,沒有中間操作是不會得到執行的)

流是一次性的(一旦一個流物件經過一個終結操作後。這個流就不能再被使用)

不會影響原資料(我們在流中可以多資料做很多處理。但是正常情況下是不會影響原來集合中的元素的。這往往也是我們期望的)

Optional

方法

在 JDK 8 中,java.util.Optional 是一個用於表示可能包含或不包含非空值的容器類。它主要用於避免空指標異常,可以更優雅地處理可能為空的值。以下是 Optional 類的一些常用方法:

  1. Optional.of(T value):建立一個包含指定非空值的 Optional 物件。如果傳入的值為 null,將丟擲 NullPointerException。

    Optional<String> optionalString = Optional.of("Hello");
    
  2. Optional.ofNullable(T value):建立一個 Optional 物件,如果傳入的值為 null,則返回一個空的 Optional 物件。

    String nullableValue = null;
    Optional<String> optionalString = Optional.ofNullable(nullableValue);
    
  3. Optional.empty():建立一個空的 Optional 物件。

    Optional<String> emptyOptional = Optional.empty();
    
  4. boolean isPresent():判斷 Optional 物件是否包含非空值。

    Optional<String> optionalString = Optional.of("Hello");
    boolean isPresent = optionalString.isPresent(); // true
    
  5. T get():獲取 Optional 物件中的值。注意,如果 Optional 物件為空,呼叫此方法會丟擲 NoSuchElementException。

    Optional<String> optionalString = Optional.of("Hello");
    String value = optionalString.get(); // "Hello"
    
  6. T orElse(T other):獲取 Optional 物件中的值,如果 Optional 為空,則返回指定的預設值。

    Optional<String> optionalString = Optional.ofNullable(null);
    String value = optionalString.orElse("Default Value"); // "Default Value"
    
  7. T orElseGet(Supplier<? extends T> other):與 orElse 類似,但是透過 Supplier 提供一個生成預設值的函式。

    Optional<String> optionalString = Optional.ofNullable(null);
    String value = optionalString.orElseGet(() -> "Default Value"); // "Default Value"
    
  8. T orElseThrow(Supplier<? extends X> exceptionSupplier):獲取 Optional 物件中的值,如果 Optional 為空,則透過 Supplier 提供的函式丟擲一個異常。

    Optional<String> optionalString = Optional.ofNullable(null);
    String value = optionalString.orElseThrow(() -> new IllegalArgumentException("Value is not present"));
    
  9. void ifPresent(Consumer<? super T> consumer):如果 Optional 物件中包含值,則執行傳入的消費者函式。

    Optional<String> optionalString = Optional.of("Hello");
    optionalString.ifPresent(val -> System.out.println("Value: " + val)); // Output: Value: Hello
    

    filter 方法,用於在 Optional 物件包含非空值時,根據指定條件進行過濾。如果滿足條件,返回原始 Optional 物件,否則返回一個空的 Optional 物件。filter 方法接受一個 Predicate 函式式介面作為引數,該介面用於定義過濾的條件。

    map 方法,用於對 Optional 物件中的值進行轉換。該方法接受一個 Function 函式式介面作為引數,用於定義值轉換的邏輯。如果 Optional 物件包含值,則 map 方法將對該值應用函式,然後返回一個包含轉換後值的新 Optional 物件。

public class OptionalDemo {
    public static void main(String[] args) {
        Author author = getAuthor();
        Optional<Author> optionalAuthor = Optional.ofNullable(author);
        optionalAuthor.ifPresent(author1 -> System.out.println(author1.getAge()));//解決傳參出現空值出現空指標異常的情況
    }
    private static Author getAuthor() {
        Author author1 = new Author(2L, "張三", 30, "喜歡探索科學的人", null);
        return null;//模擬返回空值
    }
}
public static void main(String[] args) {/*
    Author author = getAuthor();
    Optional<Author> optionalAuthor = Optional.ofNullable(author);
    optionalAuthor.ifPresent(author1 -> System.out.println(author1.getAge()));//解決傳參出現空值出現空指標異常的情況*/
    Optional<Author> optionalAuthor = getOptionalAuthor();
    optionalAuthor.ifPresent(author -> System.out.println(author.getAge()));
}
private static Optional<Author> getOptionalAuthor() {
    Author author1 = new Author(2L, "張三", 30, "喜歡探索科學的人", null);
    return Optional.ofNullable(author1);//直接進行封裝,封裝為Optional型別的
}