JDK新特性

JDK1.5新特性

JDK1.5的新特性:

自動拆裝箱 , 泛型 , 增強for , 靜態導入 , 可變參數 , 枚舉

枚舉概述: 就是一個類只能存在幾個固定的對象,那麼這個就是枚舉.我們就可以使用這些對象可以表示一些固定的值.
舉例:一週只有7天,一年只有12個月等。

枚舉

定義枚舉類要用關鍵字enum
所有枚舉類都是Enum的子類
枚舉類的第一行上必須是枚舉項,最後一個枚舉項後的分號是可以省略的,但是如果枚舉類有其他的東西,這個分號就不能省略。建議不要省略
枚舉類可以有構造器,但必須是private的,它默認的也是private的。枚舉項的用法比較特殊:枚舉(“”);
枚舉類也可以有抽象方法,但是枚舉項必須重寫該方法
枚舉在switch語句中的使用

枚舉類的常見方法

int ordinal() 返回枚舉項的序號
int compareTo(E o) 比較兩個枚舉項的 返回的是兩個枚舉項序號的 差值
String name() 獲取枚舉項的名稱
String toString()獲取枚舉項的名稱
<T> T valueOf(Class<T> type,String name) 用來獲取指定的枚舉項 參數1:枚舉類對應的字節碼對象 參數2 枚舉項的名稱
values() 獲取所有的枚舉項
此方法雖然在JDK文檔中查找不到,但每個枚舉類都具有該方法,它遍歷枚舉類的所有枚舉值非常方便

列(枚舉):

  • 1:
    public static void main(String[] args) {

    // 測試
    Direction front = Direction.FRONT ;
    Direction behind = Direction.BEHIND;
    Direction left = Direction.LEFT ;
    Direction right = Direction.RIGHT ;

    System.out.println(front.ordinal());
    System.out.println(behind.ordinal());
    System.out.println(left.ordinal());
    System.out.println(right.ordinal());

    System.out.println("----------------------------------");

    System.out.println(front.compareTo(right));

    System.out.println("----------------------------------");

    System.out.println(front.name());

    System.out.println("----------------------------------");

    System.out.println(front.toString());
    System.out.println(front);

    System.out.println("----------------------------------");

    // <T> T valueOf(Class<T> type,String name): 用來獲取指定的枚舉項
    // type: 表示的是對應的枚舉的字節碼文件對象
    // name: 就是枚舉項的名稱
    Direction direction = Direction.valueOf(Direction.class, "RIGHT") ;
    System.out.println(direction);

    System.out.println("----------------------------------");

    Direction[] directions = Direction.values() ;

    for(Direction d : directions){
    System.out.println(d);
    }

}

  • 2
    public enum Direction {
    FRONT("前"), AFTER("後"), LEFT("後"),RIGHT("右"); //下面如果有代碼,; 分號不要省略,每個枚舉項,用逗號隔開
    private Direction(String name){}
    }

//public class Direction {
// //表示前後左右四個固定的值
// //ctrl+shift+U 轉換大小寫
// public static final org.westos.demo8.Direction FRONT = new org.westos.demo8.Direction("前");
// public static final org.westos.demo8.Direction AFTER = new org.westos.demo8.Direction("後");
// public static final org.westos.demo8.Direction LEFT = new org.westos.demo8.Direction("左");
// public static final org.westos.demo8.Direction RIGHT = new org.westos.demo8.Direction("右");
// public String name;
//
// private Direction(String name) {
// this.name = name;
// }
//}
public class MyTest {
public static void main(String[] args) {
Direction front = Direction.FRONT;
Direction after = Direction.AFTER;
Direction left = Direction.LEFT;
Direction right = Direction.RIGHT;
System.out.println(front.toString());
System.out.println(after);
System.out.println(left);
System.out.println(right);

    long num = 10_000_000_000L; //_充當千位分割符

   //JUI JavaEE  B/S
   //C/S

}

}

JDK1.7新特性

二進制字面量

JDK7開始,終於可以用二進制來表示整數(byte,short,int和long)。
使用二進制字面量的好處是,可以使代碼更容易被理解。語法非常簡單,只要在二進制數值前面加 0b或者0B
int x = 0b110110

數字字面量可以出現下劃線

爲了增強對數值的閱讀性,如我們經常把數據用逗號分隔一樣。JDK7提供了_對數據分隔。
舉例:
int x = 100_1000;
注意事項:
不能出現在進制標識和數值之間
不能出現在數值開頭和結尾
不能出現在小數點旁邊

switch 語句可以用字符串

泛型可以簡化

異常的多個catch可以合併

JDK1.8新特性

新增的日期時間API

LocalDate、 LocalTime、 LocalDateTime類

LocalDate、 LocalTime、 LocalDateTime類的實例是不可變的對象,分別表示使用 ISO-8601日曆系統的日期、時間、日期和時間它們提供了簡單的日期或時間,並不包含當前的時間信息。也不包含與時區相關的信息。
注: ISO-8601日曆系統是國際標準化組織制定的現代公民的日期和時間的表示法
這些新增的日期時間API都在 java.time包下

獲取對象的方法

1通過靜態方法 now();
例如:LocalDateTime ldt = LocalDateTime.now();

方式2通過靜態方法of()方法參數可以指定年月日時分秒
    例如:LocalDateTime of = LocalDateTime.of(2018, 12, 30, 20, 20, 20);

常用方法

1.與獲取相關的方法:get系類的方法
    ldt.getYear();獲取年
    ldt.getMinute();獲取分鐘
    ldt.getHour();獲取小時
    getDayOfMonth 獲得月份天數(1-31)
    getDayOfYear 獲得年份天數(1-366)
    getDayOfWeek 獲得星期幾(返回一個 DayOfWeek枚舉值)
    getMonth 獲得月份, 返回一個 Month 枚舉值
    getMonthValue 獲得月份(1-12)
    getYear 獲得年份
2.格式化日期日期字符串的方法 format()
    例如:String yyyy = ldt.format(DateTimeFormatter.ofPattern("yyyy"));
3.轉換的方法 toLocalDate();toLocalTime();
    例如:LocalDate localDate = ldt.toLocalDate();
    例如:LocalTime localTime = ldt.toLocalTime();
4.判斷的方法
    isAfter()判斷一個日期是否在指定日期之後
    isBefore()判斷一個日期是否在指定日期之前
    isLeapYear()判斷是否是閏年注意是LocalDate類中的方法
        例如:  boolean after = ldt.isAfter(LocalDateTime.of(2024, 1, 1, 2, 3));
        例如  boolean b= LocalDate.now().isLeapYear();

5.解析的靜態方法parse("2007-12-03T10:15:30");
    paser() 將一個日期字符串解析成日期對象,注意字符串日期的寫法的格式要正確,否則解析失敗
        例如:LocalDateTime parse = LocalDateTime.parse("2007-12-03T10:15:30");

    按照我們指定的格式去解析:

    注意細節:如果用LocalDateTime 想按照我們的自定義的格式去解析,注意
    日期字符串的 年月日時分秒要寫全,不然就報錯
        LocalDateTime ldt4 = LocalDateTime.now();
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime.parse("2018-01-21 20:30:36", formatter2);

6.添加年月日時分秒的方法 plus系列的方法 都會返回一個新的LocalDateTime的對象
    LocalDateTime localDateTime = ldt.plusYears(1);
    LocalDateTime localDateTime1 = ldt.plusMonths(3);
    LocalDateTime localDateTime2=ldt.plusHours(10);
7.減去年月日時分秒的方法 minus 系列的方法 注意都會返回一個新的LocalDateTime的對象
    例如:LocalDateTime localDateTime2 = ldt.minusYears(8);
8.指定年月日時分秒的方法 with系列的方法 注意都會返回一個新的LocalDateTime的對象
    例如 LocalDateTime localDateTime3 = ldt.withYear(1998);
      //獲取這個月的第幾個星期幾是幾號,比如 TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.FRIDAY) 代表的意思是這個月的第二個星期五是幾號
          // TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.FRIDAY)
          LocalDateTime with1 = now.with(TemporalAdjusters.dayOfWeekInMonth(2,DayOfWeek.FRIDAY));

Instant時間戳類從1970-01-01 00:00:00 截止到當前時間的毫秒值

1獲取對象的方法 now()
注意默認獲取出來的是當前的美國時間和我們相差八個小時
Instant ins = Instant.now();
System.out.println(ins);
我們在東八區 所以可以加8個小時 就是我們的北京時間

  1. Instant中設置偏移量的方法:atOffset() 設置偏移量
    OffsetDateTime time = ins.atOffset(ZoneOffset.ofHours(8));
    System.out.println(time);
    3.獲取系統默認時區時間的方法atZone()
    方法的參數是要一個時區的編號可以通過時區編號類獲取出來
    ZoneId.systemDefault()獲取本地的默認時區ID
    ZonedDateTime zonedDateTime = ins.atZone(ZoneId.systemDefault());
    System.out.println(zonedDateTime);
    4.get系列的方法

    getEpochSecond() 獲取從1970-01-01 00:00:00到當前時間的秒值
    getNano()方法是把獲取到的當前時間的秒數 換算成納秒
    long epochSecond = ins.getEpochSecond();//獲取從1970-01-01 00:00:00到當前時間的秒值
    getNano()方法是把獲取到的當前時間的豪秒數 換算成納秒 比如當前時間是2018-01-01 14:00:20:30
    那就把30豪秒換算成納秒 int nano = ins.getNano();

  2. ofEpochSecond()方法 給計算機元年增加秒數
    例如 Instant instant = Instant.ofEpochSecond(5);
    System.out.println(instant);
    單位換算
    0.1 毫秒 = 10 的5次方納秒 = 100000 納秒
    1 毫秒 = 1000 微妙 = 1000000 納秒

    Duration : 用於計算兩個“時間”間隔的類

    Period : 用於計算兩個“日期”間隔的類

    列如:

    Duration類中靜態方法between()
    Instant start = Instant.now();
    for(int i=0;i<1000L;i++){
    System.out.println("循環內容");
    }
    Instant end = Instant.now();
    靜態方法:between() 計算兩個時間的間隔,默認是秒
    Duration between = Durati’on.between(start, end);
    Duration中的toMillis()方法:將秒轉成毫秒
    System.out.println(between.toMillis());

Period類 中的靜態方法between()
計算兩個日期之間的間隔
LocalDate s = LocalDate.of(1985, 03, 05);
LocalDate now = LocalDate.now();
Period be = Period.between(s, now);
System.out.println(be.getYears());間隔了多少年
System.out.println(be.getMonths());間隔了多少月
System.out.println(be.getDays());間隔多少天

TemporalAdjuster : 時間校正器,是個接口,

一般我們用該接口的一個對應的工具類 TemporalAdjusters中的一些常量,來指定日期

例如:

LocalDate now = LocalDate.now();
System.out.println(now);
1 使用TemporalAdjusters自帶的常量來設置日期
LocalDate with = now.with(TemporalAdjusters.lastDayOfYear());
System.out.println(with);
2 採用TemporalAdjusters中的next方法來指定日期
LocalDate date = now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(date);
例如:TemporalAdjusters.next(DayOfWeek.SUNDAY) 本週的星期天
例如:TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY) 下一週的星期一
3 採用自定義的方式來指定日期 比如指定下個工作日
LocalDateTime ldt = LocalDateTime.now();
LocalDateTime workDay = ldt.with(new TemporalAdjuster() {br/>@Override
public Temporal adjustInto(Temporal temporal) {
//向下轉型
LocalDateTime ld = (LocalDateTime) temporal;
//獲取這周的星期幾
DayOfWeek dayOfWeek = ld.getDayOfWeek();
if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
return ld.plusDays(3);//如果這天是星期五,那下個工做日就加3天
} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return ld.plusDays(2);//如果這天是星期六,那下個工做日就加2天
} else {
//其他就加一天
return ld.plusDays(1);
}
}
});

System.out.println(workDay);

DateTimeFormatter :解析和格式化日期或時間的類

1.獲取對象的方式,通過靜態方法ofPattern("yyyy-MM-dd");
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDateTime now = LocalDateTime.now();
2.format()方法把一個日期對象的默認格式 格式化成指定的格式
String format1 = dateFormat.format(now);
System.out.println(format1);
3.格式化日期 方式2使用日期類中的format方法 傳入一個日期格式化類對象

LocalDateTime now1 = LocalDateTime.now();
使用日期類中的format方法 傳入一個日期格式化類對象
使用DateTimeFormatter中提供好的日期格式常量
now1.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);

4.使用自定義的日期格式格式化字符串
DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");//自定義一個日期格式
String time = now1.format(timeFormat);
System.out.println(time);

  1. 把一個日期字符串轉成日期對象
    使用日期類中的parse方法傳入一個日期字符串,傳入對應的日期格式化類
    DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    LocalDateTime parse = LocalDateTime.parse(time, timeFormat);
    System.out.println(parse);

    ZonedDate,ZonedTime、ZonedDateTime : 帶時區的時間或日期

    用法和 LocalDate、 LocalTime、 LocalDateTime 一樣 只不過ZonedDate,ZonedTime、ZonedDateTime 這三個帶有當前系統的默認時區

    ZoneID 世界時區類

    1.獲取世界各個地方的時區的集合 的方法getAvailableZoneIds()
    使用ZoneID中的靜態方法getAvailableZoneIds();來獲取
    例如:Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
    2.獲取系統默認時區的ID
    ZoneId zoneId = ZoneId.systemDefault(); //Asia/Shanghai
    3.獲取帶有時區的日期時間對象
    //創建日期對象
    LocalDateTime now = LocalDateTime.now();
    //獲取不同國家的日期時間根據各個地區的時區ID名創建對象
    ZoneId timeID = ZoneId.of("Asia/Shanghai");
    //根據時區ID獲取帶有時區的日期時間對象
    ZonedDateTime time = now.atZone(timeID);
    System.out.println(time);
    //方式2 通過時區ID 獲取日期對象
    LocalDateTime now2 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
    System.out.println(now2);

    Lambda表達式

    Lambda 是一個匿名函數,我們可以把 Lambda表達式理解爲是一段可以傳遞的代碼(將代碼像數據一樣進行傳遞)。可以寫出更簡潔、更靈活的代碼。作爲一種更緊湊的代碼風格,使Java的語言表達能力得到了提升。
    public interface MyInterface {
    void show(int a,int b);
    }
    public class MyTest {
    public static void main(String[] args) {
    //JDK1.8之後提供了一種新的語法 叫做 Lambda表達式,可以簡化我們對匿名內部類的寫法,也可以作爲參數傳遞
    //可以使用匿名內部類來創建該接口的一個子類對象
    MyInterface myInterface = new MyInterface() {br/>@Override
    public void show(int a, int b) {
    System.out.println(a + b);
    }
    };
    myInterface.show(10, 20);
    //上面匿名內部類的寫法,我可以用Lambda表達式來簡化
    //Lambda 引入了一個箭頭 -> 符號,將我們的表達式分爲左右兩部分
    //箭頭左邊,就是接口中抽象方法的參數列表,箭頭右邊,是你對接口中的抽象方法的具體的重寫邏輯
    //參數列表中的數據類型 可以省略不寫
    MyInterface myInterface3 = (x, y) -> System.out.println(x + y);
    //當然你可以寫上參數的,數據類型
    MyInterface myInterface2 = (int x, int y) -> System.out.println(x + y);

    //箭頭右邊對接口中方法的具體實現邏輯,如果只有一行代碼,那麼{}也可以省略不寫,當然也可以寫上
    MyInterface myInterface4 = (int x, int y) -> {
        System.out.println(x + y);
    };
    
    //如果你對接口中的抽象方法的實現邏輯有多條語句,那麼這個{} 必須寫上
    MyInterface myInterface5 = (int x, int y) -> {
        System.out.println(x + y);
        System.out.println(x-y);
        System.out.println(x*y);
    };
    myInterface2.show(10, 2000);

    }
    }
    public class MyTest2 {
    public static void main(String[] args) {
    MyInterface2 myInterface2 = new MyInterface2() {br/>@Override
    public int test(int a, int b) {
    return a + b;
    }
    };

    System.out.println("---------------------");
    //如果你對接口中的抽象方法具體的實現邏輯是一行語句,並且還有返回值,那麼{}就省略不寫
    MyInterface2 myInterface3 = (x, y) -> x + y;
    //如果說你要將return關鍵字寫上,那麼你也要將{}寫上
    MyInterface2 myInterface4 = (x, y) -> {
        return x + y;
    };
    
    myTest(new MyInterface() {
        @Override
        public void show(int a, int b) {
            System.out.println(a+b);
        }
    });
    MyInterface myInterface=(x, y) -> System.out.println(x + y);
    myTest(myInterface);

    }

    private static void myTest(MyInterface myInterface) {
    myInterface.show(10,20);
    }
    }
    通過上面的對比,發現Lambda表達式式書寫起來更爲簡潔
    那我們具體來看一下Lambda表達式的書寫語法
    Lambda 表達式在Java 語言中引入了一個新的語法元素和操作符。這個操作符爲 “ ->” , 該操作符被稱爲 Lambda 操作符或箭頭操作符。它將 Lambda 分爲兩個部分:
    左側: 指定了 Lambda 表達式需要的所有參數
    右側: 指定了 Lambda 體,即 Lambda 表達式要執行的功能。
    public interface MyInteface3 {
    void test();
    void show();
    }
    public class MyTest2 {
    public static void main(String[] args) {
    new MyInteface3(){br/>@Override
    public void test() {

        }
    
        @Override
        public void show() {
    
        }
    };

    //Lambda 需要 函數式接口的支持
    // 函數式接口:這個接口中,僅僅只有 一個抽象方法
    // 函數式接口可以使用註解 @FunctionalInterface 來檢測這個接口是不是函數式接口
    //

    }
    }
    public class MyTest3 {
    public static void main(String[] args) {

    Integer[] integers=new Integer[]{10,30,40,1,3,5};
    Arrays.sort(integers, (a, b) -> b-a);
    
    System.out.println(Arrays.toString(integers));

    }
    }
    上述 Lambda 表達式中的參數類型都是由編譯器推斷得出的。 Lambda 表達式中無需指定類型,程序依然可以編譯,這是因爲 javac 根據程序的上下文,在後臺推斷出了參數的類型。 Lambda 表達式的類型依賴於上下文環境,是由編譯器推斷出來的。這就是所謂的“類型推斷”.

    函數式接口

    Lambda表達式就是對函數式接口的一種簡寫方式,所以只有是函數式接口,我們才能用Lambda表達式.再換句話說,Lambda表達式需要函數式接口的支持,那函數式接口我們可以自己定義,當然JDK1.8也給我們提供了一些現成的函數式接口.

    函數式接口的定義是: 只包含一個抽象方法的接口,稱爲函數式接口。

    你可以通過 Lambda 表達式來創建該接口的對象
    我們可以在任意函數式接口上使用 @FunctionalInterface 註解,這樣做可以檢查它是否是一個函數式接口,同時 javadoc 也會包含一條聲明,說明這個接口是一個函數式接口.

    Java中提供的4大核心函數式接口

    函數式接口 參數類型 返回類型 用途
    Consumer<T>
    消費型接口 T void 對類型爲T的對象應用操
    作,包含方法:
    void accept(T t)
    Supplier<T>
    供給型接口 無 T 返回類型爲T的對象,包
    含方法: T get();
    Function<T, R>
    函數型接口
    T R 對類型爲T的對象應用操
    作,並返回結果。結果
    是R類型的對象。包含方
    法: R apply(T t);
    Predicate<T> 斷言型接口
    T boolean 確定類型爲T的對象是否
    滿足某約束,並返回
    boolean 值。包含方法
    boolean test(T t);

    其他函數式接口

    函數式接口 參數類型 返回類型 用途
    BiFunction<T,U,R>
    T U R 對類型爲 T, U 參數應用
    操作, 返回 R 類型的結
    果。 包含方法爲
    R apply(T t, U u);
    UnaryOperator<T>
    (Function的子接口)
    T T 對類型爲T的對象進行一
    元運算, 並返回T類型的
    結果。 包含方法爲
    T apply(T t);
    BinaryOperator<T>
    (BiFunction的子接口) T T T 對類型爲T的對象進行二
    元運算, 並返回T類型的
    結果。 包含方法爲
    T apply(T t1, T t2);
    BiConsumer<T,U>
    T U void 對類型爲T, U 參數應用
    操作。 包含方法爲
    void accept(T t, U u)
    ToIntFunction<T>
    ToLongFunction<T>
    ToDoubleFunction<T>
    T int
    long
    double 分 別 計 算 int 、 long 、
    double、 值的函數
    IntFunction<R>
    LongFunction<R>
    DoubleFunction<R>
    int
    long
    double R 參數分別爲int、 long、
    double 類型的函數

    Stream API

    Stream 是 Java8 中處理集合的關鍵抽象概念,
    它可以指定你希望對集合進行的操作,
    可以執行非常複雜的查找、過濾和映射數據等操作。
    使用Stream API 對集合數據進行操作,就類似於使用 SQL 執行的數據庫查詢。也可以使用 Stream API 來並行執行操作。
    簡而言之,Stream API 提供了一種高效且易於使用的處理數據的方式。

    流到底是什麼呢?

    是數據渠道,用於操作數據源(集合、數組等)所生成的元素序列。
    集合講的是數據,流講的是計算!

    • 注意:
      ①Stream 自己不會存儲元素。
      ②Stream 不會改變源對象。相反,他們會返回一個持有結果的新Stream。
      ③Stream 操作是延遲執行的。這意味着他們會等到需要結果的時候才執行。

      steam操作的三個步驟

      Stream 的操作三個步驟
      1.創建 Stream
      一個數據源(如:集合、數組),獲取一個流
       2.中間操作
      一箇中間操作鏈,對數據源的數據進行處理
       3.終止操作(終端操作)
      一個終止操作,執行中間操作鏈,併產生結果

創建Stream的方式

1.Java8 中的 Collection 接口被擴展,提供了
  兩個獲取流的方法:

 default Stream<E> stream() : 返回一個順序流
 default Stream<E> parallelStream() : 返回一個並行流
2.Java8 中的 Arrays 的靜態方法 stream() 可以獲取數組流:
 static <T> Stream<T> stream(T[] array): 返回一個流
重載形式,能夠處理對應基本類型的數組:
public static IntStream stream(int[] array)
 public static LongStream stream(long[] array)
 public static DoubleStream stream(double[] array)
3.由值創建流,可以使用靜態方法 Stream.of(), 通過顯示值創建一個流。它可以接收任意數量的參數。
 public static<T> Stream<T> of(T... values) : 返回一個流
4.由函數創建流:創建無限流可以使用靜態方法 Stream.iterate()和Stream.generate(), 創建無限流。
public static<T> Stream<T> iterate(final T seed, finalUnaryOperator<T> f) 迭代
public static<T> Stream<T> generate(Supplier<T> s) 生成

Stream 的中間操作

多箇中間操作可以連接起來形成一個流水線,除非流水線上觸發終止操作,否則中間操作不會執行任何的處理!
而在終止操作時一次性全部處理,稱爲“惰性求值”。
    1. 篩選與切片
      filter(Predicate p) 過濾 接收 Lambda , 從流中排除某些元素。
      distinct() 去重,通過流所生成元素的 hashCode() 和 equals() 去除重複元素
      limit(long maxSize) 截斷流,使其元素不超過給定數量。
      skip(long n) 跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。與 limit(n) 互補
  • 2.映射
    map(Function f) 接收一個函數作爲參數,該函數會被應用到每個元素上,並將其映射成一個新的元素。
    flatMap(Function f) 接收一個函數作爲參數,將流中的每個值都換成另一個流,然後把所有流連接成一個流.
    mapToDouble(ToDoubleFunction f) 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的 DoubleStream。
    mapToInt(ToIntFunction f) 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的 IntStream。
    mapToLong(ToLongFunction f) 接收一個函數作爲參數,該函數會被應用到每個元素上,產生一個新的 LongStream。

  • 3.排序
    sorted() 產生一個新流,其中按自然順序排序 元素實現Compareble接口
    sorted(Comparator comp) 產生一個新流,其中按比較器順序排序 傳入一個比較器

    steam的終止操作

    終端操作會從流的流水線生成結果。其結果可以是任何不是流的值,例如:List、Integer,甚至是 void 。

1.查找與匹配
    allMatch(Predicate p)   檢查是否匹配所有元素  比如判斷 所有員工的年齡都是17歲 如果有一個不是,就返回false
    anyMatch(Predicate p)   檢查是否至少匹配一個元素  比如判斷是否有姓王的員工,如果至少有一個就返回true
    noneMatch(Predicate p)  檢查是否沒有匹配所有元素   比如判斷所有員工的工資都是否都是高於3000 如果有一個人低於3000 就返回false
    findFirst()     返回第一個元素  比如獲取工資最高的人  或者 獲取工資最高的值是
    findAny()       返回當前流中的任意元素   比如隨便獲取一個姓王的員工
    count() 返回流中元素總數  
    max(Comparator c)   返回流中最大值  比如:獲取最大年齡值
    min(Comparator c)   返回流中最小值  比如:獲取最小年齡的值
    forEach(Consumer c) 內部迭代(使用 Collection 接口需要用戶去做迭代,稱爲外部迭代。相反,Stream API 使用內部迭代——它幫你把迭代做了)
2.歸約
    reduce(T iden, BinaryOperator b)  參1 是起始值, 參2 二元運算  可以將流中元素反覆結合起來,得到一個值。返回 T  比如: 求集合中元素的累加總和 
    reduce(BinaryOperator b) 這個方法沒有起始值  可以將流中元素反覆結合起來,得到一個值。返回 Optional<T>  , 比如你可以算所有員工工資的總和
    備註:map 和 reduce 的連接通常稱爲 map-reduce 模式,因 Google 用它來進行網絡搜索而出名。
3.收集
    collect(Collector c)    將流轉換爲其他形式。接收一個 Collector接口的實現,用於給Stream中元素做彙總的方法
    Collector 接口中方法的實現決定了如何對流執行收集操作(如收集到 List、Set、Map)。
    但是 Collectors 實用類提供了很多靜態方法,可以方便地創建常見收集器實例,具體方法與實例如下
 4.Collectors 中的方法
    List<T> toList()        把流中元素收集到List   比如把所有員工的名字通過map()方法提取出來之後,在放到List集合中去
        例子:List<Employee> emps= list.stream().map(提取名字).collect(Collectors.toList());
    Set<T>  toSet()     把流中元素收集到Set  比如把所有員工的名字通過map()方法提取出來之後,在放到Set集合中去
        例子:Set<Employee> emps= list.stream().collect(Collectors.toSet());
    Collection<T> toCollection()        把流中元素收集到創建的集合 比如把所有員工的名字通過map()方法提取出來之後,在放到自己指定的集合中去
        例子:Collection<Employee>emps=list.stream().map(提取名字).collect(Collectors.toCollection(ArrayList::new));
    Long counting()     計算流中元素的個數
        例子:long count = list.stream().collect(Collectors.counting());
    Integer summingInt()    對流中元素的整數屬性求和
        例子:inttotal=list.stream().collect(Collectors.summingInt(Employee::getSalary));
    Double averagingInt()       計算流中元素Integer屬性的平均值
        例子:doubleavg= list.stream().collect(Collectors.averagingInt(Employee::getSalary));
    IntSummaryStatistics summarizingInt()   收集流中Integer屬性的統計值。
        例子:DoubleSummaryStatistics dss= list.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
           從DoubleSummaryStatistics 中可以獲取最大值,平均值等
                                    double average = dss.getAverage();
                    long count = dss.getCount();
                            double max = dss.getMax();
    String joining() 連接流中每個字符串  比如把所有人的名字提取出來,在通過"-"橫槓拼接起來
        例子:String str= list.stream().map(Employee::getName).collect(Collectors.joining("-"));
    Optional<T> maxBy() 根據比較器選擇最大值  比如求最大工資
        例子:Optional<Emp>max= list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));
    Optional<T> minBy() 根據比較器選擇最小值  比如求最小工資
        例子:Optional<Emp> min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));
    歸約產生的類型 reducing() 從一個作爲累加器的初始值開始,利用BinaryOperator與流中元素逐個結合,從而歸約成單個值
        例子:inttotal=list.stream().collect(Collectors.reducing(0, Employee::getSalar, Integer::sum));
    轉換函數返回的類型 collectingAndThen()       包裹另一個收集器,對其結果轉換函數
        例子:inthow= list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
    Map<K, List<T>> groupingBy() 根據某屬性值對流分組,屬性爲K,結果爲V  比如按照 狀態分組
        例子:Map<Emp.Status, List<Emp>> map= list.stream().collect(Collectors.groupingBy(Employee::getStatus));
    Map<Boolean, List<T>> partitioningBy() 根據true或false進行分區 比如 工資大於等於6000的一個區,小於6000的一個區
        例子:Map<Boolean,List<Emp>>vd= list.stream().collect(Collectors.partitioningBy(Employee::getSalary));

並行流與串行流

並行流就是把一個內容分成多個數據塊,並用不同的線程分別處理每個數據塊的流。
Java 8 中將並行進行了優化,我們可以很容易的對數據進行並行操作。
Stream API 可以聲明性地通過 parallel() 與sequential() 在並行流與順序流之間進行切換。

列子:

public Employee() {
}

public Employee(String name) {
    this.name = name;
}

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

public Employee(int id, String name, int age, double salary) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.salary = salary;
}

public Employee(int id, String name, int age, double salary, Status status) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.salary = salary;
    this.status = status;
}

public Status getStatus() {
    return status;
}

public void setStatus(Status status) {
    this.status = status;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

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;
}

public double getSalary() {
    return salary;
}

public void setSalary(double salary) {
    this.salary = salary;
}

public String show() {
    return "測試方法引用!";
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result + id;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    long temp;
    temp = Double.doubleToLongBits(salary);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Employee other = (Employee) obj;
    if (age != other.age)
        return false;
    if (id != other.id)
        return false;
    if (name == null) {
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
        return false;
    return true;
}

@Override
public String toString() {
    return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + ", status=" + status
            + "]";
}

//枚舉
public enum Status {
    FREE, //空閒
    BUSY, //繁忙
    VOCATION;//休假
}

}
public class MyTest {
public static void main(String[] args) {
//**Stream 的操作三個步驟
//1. 創建 Stream
//一個數據源(如:集合、數組),獲取一個流
//2. 中間操作
//一箇中間操作鏈,對數據源的數據進行處理
//3. 終止操作(終端操作)
//一個終止操作,執行中間操作鏈,併產生結果
//我們會創建流跟集合關聯起來,關聯起來後,我們是想要使用這個流對集合中的元素,進行一些列的中間操作
//1. 篩選與切片
//filter(Predicate p) 過濾 接收 Lambda ,從流中排除某些元素。
//distinct() 去重,通過流所生成元素的 hashCode () 和 equals () 去除重複元素
//limit( long maxSize)截斷流,使其元素不超過給定數量。
//skip( long n)跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。與 limit (n) 互補
//

    List<Employee> emps = Arrays.asList(
            new Employee(102, "李四", 59, 6666.66),
            new Employee(101, "張三", 18, 9999.99),
            new Employee(103, "王五", 28, 3333.33),
            new Employee(104, "趙六", 8, 7777.77),
            new Employee(104, "趙六", 8, 7777.77),
            new Employee(104, "趙六", 8, 7777.77),
            new Employee(105, "田七", 38, 5555.55)
    );
    //獲取流跟集合進行關聯
    Stream<Employee> stream = emps.stream();
    //那麼我們通過這個流,對集合中的元素進行一些列的中間操作
    //獲取工資大於6000塊錢的員工
   // Predicate<T> 斷言型接口
    Stream<Employee> employeeStream = stream.filter((employee) -> employee.getSalary()>6666);
    //終止操作沒有執行,其實中間操作,沒有執行
    employeeStream.forEach(System.out::println);
    System.out.println("--------------------------");
    Stream<Employee> stream2 = emps.stream();
    //我要過濾出名字是趙六的員工
    stream2.filter((emp)->emp.getName().equals("趙六")).forEach(System.out::println);

}

}
public class MyTest2 {
public static void main(String[] args) {
//distinct() 去重,通過流所生成元素的 hashCode () 和 equals () 去除重複元素
List<Employee> emps = Arrays.asList(
new Employee(102, "李四", 59, 6666.66),
new Employee(101, "張三", 18, 9999.99),
new Employee(103, "王五", 28, 3333.33),
new Employee(104, "趙六", 8, 7777.77),
new Employee(104, "趙六", 8, 7777.77),
new Employee(104, "趙六", 8, 7777.77),
new Employee(105, "田七", 38, 5555.55)
);

    Stream<Employee> stream = emps.stream();
    Stream<Employee> employeeStream = stream.filter((emp) -> emp.getSalary() > 5000);
    Stream<Employee> distinct = employeeStream.distinct();
    distinct.forEach(System.out::println);
}

}
public class MyTest3 {
public static void main(String[] args) {
List<Employee> emps = Arrays.asList(
new Employee(102, "李四", 59, 6666.66),
new Employee(101, "張三", 18, 9999.99),
new Employee(103, "王五", 28, 3333.33),
new Employee(104, "趙六", 8, 7777.771),
new Employee(104, "趙六", 8, 7777.772),
new Employee(104, "趙六", 8, 7777.773),
new Employee(105, "田七", 38, 5555.55)
);

    Stream<Employee> stream = emps.stream();
    Stream<Employee> stream1 = stream.filter((emp) -> emp.getName().equals("趙六"));
   // Stream<Employee> limit = stream1.limit(2); //截斷流
    //skip( long n)跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。與 limit (n) 互補
    Stream<Employee> skip = stream1.skip(1);//跳過前幾個元素,留下剩下的
    skip.forEach(System.out::println);

}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章