溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JDK新特性

發(fā)布時間:2020-06-12 02:59:19 來源:網(wǎng)絡(luò) 閱讀:370 作者:龍逸塵 欄目:編程語言

JDK1.5新特性

JDK1.5的新特性:

自動拆裝箱 , 泛型 , 增強for , 靜態(tài)導(dǎo)入 , 可變參數(shù) , 枚舉

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

枚舉

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

枚舉類的常見方法

int ordinal() 返回枚舉項的序號
int compareTo(E o) 比較兩個枚舉項的 返回的是兩個枚舉項序號的 差值
String name() 獲取枚舉項的名稱
String toString()獲取枚舉項的名稱
<T> T valueOf(Class<T> type,String name) 用來獲取指定的枚舉項 參數(shù)1:枚舉類對應(yīng)的字節(jié)碼對象 參數(shù)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: 表示的是對應(yīng)的枚舉的字節(jié)碼文件對象
    // 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 轉(zhuǎn)換大小寫
// 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; //_充當(dāng)千位分割符

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

}

}

JDK1.7新特性

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

為了增強對數(shù)值的閱讀性,如我們經(jīng)常把數(shù)據(jù)用逗號分隔一樣。JDK7提供了_對數(shù)據(jù)分隔。
舉例:
int x = 100_1000;
注意事項:
不能出現(xiàn)在進制標(biāo)識和數(shù)值之間
不能出現(xiàn)在數(shù)值開頭和結(jié)尾
不能出現(xiàn)在小數(shù)點旁邊

switch 語句可以用字符串
泛型可以簡化
異常的多個catch可以合并

JDK1.8新特性

新增的日期時間API
LocalDate、 LocalTime、 LocalDateTime類

LocalDate、 LocalTime、 LocalDateTime類的實例是不可變的對象,分別表示使用 ISO-8601日歷系統(tǒng)的日期、時間、日期和時間它們提供了簡單的日期或時間,并不包含當(dāng)前的時間信息。也不包含與時區(qū)相關(guān)的信息。
注: ISO-8601日歷系統(tǒng)是國際標(biāo)準(zhǔn)化組織制定的現(xiàn)代公民的日期和時間的表示法
這些新增的日期時間API都在 java.time包下

獲取對象的方法

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

方式2通過靜態(tài)方法of()方法參數(shù)可以指定年月日時分秒
    例如:LocalDateTime of = LocalDateTime.of(2018, 12, 30, 20, 20, 20);
常用方法
1.與獲取相關(guān)的方法:get系類的方法
    ldt.getYear();獲取年
    ldt.getMinute();獲取分鐘
    ldt.getHour();獲取小時
    getDayOfMonth 獲得月份天數(shù)(1-31)
    getDayOfYear 獲得年份天數(shù)(1-366)
    getDayOfWeek 獲得星期幾(返回一個 DayOfWeek枚舉值)
    getMonth 獲得月份, 返回一個 Month 枚舉值
    getMonthValue 獲得月份(1-12)
    getYear 獲得年份
2.格式化日期日期字符串的方法 format()
    例如:String yyyy = ldt.format(DateTimeFormatter.ofPattern("yyyy"));
3.轉(zhuǎn)換的方法 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.解析的靜態(tài)方法parse("2007-12-03T10:15:30");
    paser() 將一個日期字符串解析成日期對象,注意字符串日期的寫法的格式要正確,否則解析失敗
        例如:LocalDateTime parse = LocalDateTime.parse("2007-12-03T10:15:30");

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

    注意細節(jié):如果用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 with2 = now.with(TemporalAdjusters.dayOfWeekInMonth(2,DayOfWeek.FRIDAY));

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

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

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

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

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

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

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

    列如:

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

Period類 中的靜態(tài)方法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 : 時間校正器,是個接口,

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

例如:

LocalDate now = LocalDate.now();
System.out.println(now);
1 使用TemporalAdjusters自帶的常量來設(shè)置日期
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() {@Override
br/>@Override
//向下轉(zhuǎn)型
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.獲取對象的方式,通過靜態(tài)方法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. 把一個日期字符串轉(zhuǎn)成日期對象
    使用日期類中的parse方法傳入一個日期字符串,傳入對應(yīng)的日期格式化類
    DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    LocalDateTime parse = LocalDateTime.parse(time, timeFormat);
    System.out.println(parse);

    ZonedDate,ZonedTime、ZonedDateTime : 帶時區(qū)的時間或日期

    用法和 LocalDate、 LocalTime、 LocalDateTime 一樣 只不過ZonedDate,ZonedTime、ZonedDateTime 這三個帶有當(dāng)前系統(tǒng)的默認時區(qū)

    ZoneID 世界時區(qū)類

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

    Lambda表達式

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

    //箭頭右邊對接口中方法的具體實現(xiàn)邏輯,如果只有一行代碼,那么{}也可以省略不寫,當(dāng)然也可以寫上
    MyInterface myInterface4 = (int x, int y) -> {
        System.out.println(x + y);
    };
    
    //如果你對接口中的抽象方法的實現(xiàn)邏輯有多條語句,那么這個{} 必須寫上
    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() {@Override
    br/>@Override
    return a + b;
    }
    };

    System.out.println("---------------------");
    //如果你對接口中的抽象方法具體的實現(xiàn)邏輯是一行語句,并且還有返回值,那么{}就省略不寫
    MyInterface2 myInterface3 = (x, y) -> x + y;
    //如果說你要將return關(guān)鍵字寫上,那么你也要將{}寫上
    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);
    }
    }
    通過上面的對比,發(fā)現(xiàn)Lambda表達式式書寫起來更為簡潔
    那我們具體來看一下Lambda表達式的書寫語法
    Lambda 表達式在Java 語言中引入了一個新的語法元素和操作符。這個操作符為 “ ->” , 該操作符被稱為 Lambda 操作符或箭頭操作符。它將 Lambda 分為兩個部分:
    左側(cè): 指定了 Lambda 表達式需要的所有參數(shù)
    右側(cè): 指定了 Lambda 體,即 Lambda 表達式要執(zhí)行的功能。
    public interface MyInteface3 {
    void test();
    void show();
    }
    public class MyTest2 {
    public static void main(String[] args) {
    new MyInteface3(){@Override
    br/>@Override

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

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

    }
    }
    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 表達式中的參數(shù)類型都是由編譯器推斷得出的。 Lambda 表達式中無需指定類型,程序依然可以編譯,這是因為 javac 根據(jù)程序的上下文,在后臺推斷出了參數(shù)的類型。 Lambda 表達式的類型依賴于上下文環(huán)境,是由編譯器推斷出來的。這就是所謂的“類型推斷”.

    函數(shù)式接口

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

    函數(shù)式接口的定義是: 只包含一個抽象方法的接口,稱為函數(shù)式接口。

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

    Java中提供的4大核心函數(shù)式接口

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

    其他函數(shù)式接口

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

    Stream API

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

    流到底是什么呢?

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

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

      steam操作的三個步驟

      Stream 的操作三個步驟
      1.創(chuàng)建 Stream
      一個數(shù)據(jù)源(如:集合、數(shù)組),獲取一個流
      ? 2.中間操作
      一個中間操作鏈,對數(shù)據(jù)源的數(shù)據(jù)進行處理
      ? 3.終止操作(終端操作)
      一個終止操作,執(zhí)行中間操作鏈,并產(chǎn)生結(jié)果

創(chuàng)建Stream的方式

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

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

Stream 的中間操作

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

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

    steam的終止操作

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

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

并行流與串行流

并行流就是把一個內(nèi)容分成多個數(shù)據(jù)塊,并用不同的線程分別處理每個數(shù)據(jù)塊的流。
Java 8 中將并行進行了優(yōu)化,我們可以很容易的對數(shù)據(jù)進行并行操作。
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. 創(chuàng)建 Stream
//一個數(shù)據(jù)源(如:集合、數(shù)組),獲取一個流
//?2. 中間操作
//一個中間操作鏈,對數(shù)據(jù)源的數(shù)據(jù)進行處理
//?3. 終止操作(終端操作)
//一個終止操作,執(zhí)行中間操作鏈,并產(chǎn)生結(jié)果
//我們會創(chuàng)建流跟集合關(guān)聯(lián)起來,關(guān)聯(lián)起來后,我們是想要使用這個流對集合中的元素,進行一些列的中間操作
//1. 篩選與切片
//filter(Predicate p) 過濾 接收 Lambda ,從流中排除某些元素。
//distinct() 去重,通過流所生成元素的 hashCode () 和 equals () 去除重復(fù)元素
//limit( long maxSize)截斷流,使其元素不超過給定數(shù)量。
//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)
    );
    //獲取流跟集合進行關(guān)聯(lián)
    Stream<Employee> stream = emps.stream();
    //那么我們通過這個流,對集合中的元素進行一些列的中間操作
    //獲取工資大于6000塊錢的員工
   // Predicate<T> 斷言型接口
    Stream<Employee> employeeStream = stream.filter((employee) -> employee.getSalary()>6666);
    //終止操作沒有執(zhí)行,其實中間操作,沒有執(zhí)行
    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 () 去除重復(fù)元素
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);

}

}

向AI問一下細節(jié)
推薦閱讀:
  1. jdk1.8新特性
  2. jdk8新特性

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI