JDK新特性

JDK1.5新特性

JDK1.5的新特性:

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

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

成都創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比開原網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式開原網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋開原地區(qū)。費(fèi)用合理售后完善,10多年實(shí)體公司更值得信賴。

枚舉

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

枚舉類的常見方法

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

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

    // 測(cè)試
    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): 用來獲取指定的枚舉項(xiàng)
    // type: 表示的是對(duì)應(yīng)的枚舉的字節(jié)碼文件對(duì)象
    // name: 就是枚舉項(xiàng)的名稱
    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("右"); //下面如果有代碼,; 分號(hào)不要省略,每個(gè)枚舉項(xiàng),用逗號(hào)隔開
    private Direction(String name){}
    }

//public class Direction {
// //表示前后左右四個(gè)固定的值
// //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新特性

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

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

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

JDK1.8新特性

新增的日期時(shí)間API
LocalDate、 LocalTime、 LocalDateTime類

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

獲取對(duì)象的方法

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

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

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

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

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

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

1獲取對(duì)象的方法 now()
注意默認(rèn)獲取出來的是當(dāng)前的美國時(shí)間和我們相差八個(gè)小時(shí)
Instant ins = Instant.now();
System.out.println(ins);
我們?cè)跂|八區(qū) 所以可以加8個(gè)小時(shí) 就是我們的北京時(shí)間

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

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

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

    Duration : 用于計(jì)算兩個(gè)“時(shí)間”間隔的類

    Period : 用于計(jì)算兩個(gè)“日期”間隔的類

    列如:

    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() 計(jì)算兩個(gè)時(shí)間的間隔,默認(rèn)是秒
    Duration between = Durati’on.between(start, end);
    Duration中的toMillis()方法:將秒轉(zhuǎn)成毫秒
    System.out.println(between.toMillis());

Period類 中的靜態(tài)方法between()
計(jì)算兩個(gè)日期之間的間隔
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 : 時(shí)間校正器,是個(gè)接口,

一般我們用該接口的一個(gè)對(duì)應(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 采用自定義的方式來指定日期 比如指定下個(gè)工作日
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);//如果這天是星期五,那下個(gè)工做日就加3天
} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return ld.plusDays(2);//如果這天是星期六,那下個(gè)工做日就加2天
} else {
//其他就加一天
return ld.plusDays(1);
}
}
});

System.out.println(workDay);

DateTimeFormatter :解析和格式化日期或時(shí)間的類

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

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

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

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

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

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

    ZoneID 世界時(shí)區(qū)類

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

    Lambda表達(dá)式

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

    //箭頭右邊對(duì)接口中方法的具體實(shí)現(xiàn)邏輯,如果只有一行代碼,那么{}也可以省略不寫,當(dāng)然也可以寫上
    MyInterface myInterface4 = (int x, int y) -> {
        System.out.println(x + y);
    };
    
    //如果你對(duì)接口中的抽象方法的實(shí)現(xiàn)邏輯有多條語句,那么這個(gè){} 必須寫上
    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("---------------------");
    //如果你對(duì)接口中的抽象方法具體的實(shí)現(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);
    }
    }
    通過上面的對(duì)比,發(fā)現(xiàn)Lambda表達(dá)式式書寫起來更為簡潔
    那我們具體來看一下Lambda表達(dá)式的書寫語法
    Lambda 表達(dá)式在Java 語言中引入了一個(gè)新的語法元素和操作符。這個(gè)操作符為 “ ->” , 該操作符被稱為 Lambda 操作符或箭頭操作符。它將 Lambda 分為兩個(gè)部分:
    左側(cè): 指定了 Lambda 表達(dá)式需要的所有參數(shù)
    右側(cè): 指定了 Lambda 體,即 Lambda 表達(dá)式要執(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ù)式接口:這個(gè)接口中,僅僅只有 一個(gè)抽象方法
    // 函數(shù)式接口可以使用注解 @FunctionalInterface 來檢測(cè)這個(gè)接口是不是函數(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 表達(dá)式中的參數(shù)類型都是由編譯器推斷得出的。 Lambda 表達(dá)式中無需指定類型,程序依然可以編譯,這是因?yàn)?javac 根據(jù)程序的上下文,在后臺(tái)推斷出了參數(shù)的類型。 Lambda 表達(dá)式的類型依賴于上下文環(huán)境,是由編譯器推斷出來的。這就是所謂的“類型推斷”.

    函數(shù)式接口

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

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

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

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

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

    其他函數(shù)式接口

    函數(shù)式接口 參數(shù)類型 返回類型 用途
    BiFunction<T,U,R>
    T U R 對(duì)類型為 T, U 參數(shù)應(yīng)用
    操作, 返回 R 類型的結(jié)
    果。 包含方法為
    R apply(T t, U u);
    UnaryOperator<T>
    (Function的子接口)
    T T 對(duì)類型為T的對(duì)象進(jìn)行一
    元運(yùn)算, 并返回T類型的
    結(jié)果。 包含方法為
    T apply(T t);
    BinaryOperator<T>
    (BiFunction的子接口) T T T 對(duì)類型為T的對(duì)象進(jìn)行二
    元運(yùn)算, 并返回T類型的
    結(jié)果。 包含方法為
    T apply(T t1, T t2);
    BiConsumer<T,U>
    T U void 對(duì)類型為T, U 參數(shù)應(yīng)用
    操作。 包含方法為
    void accept(T t, U u)
    ToIntFunction<T>
    ToLongFunction<T>
    ToDoubleFunction<T>
    T int
    long
    double 分 別 計(jì) 算 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)鍵抽象概念,
    它可以指定你希望對(duì)集合進(jìn)行的操作,
    可以執(zhí)行非常復(fù)雜的查找、過濾和映射數(shù)據(jù)等操作。
    使用Stream API 對(duì)集合數(shù)據(jù)進(jìn)行操作,就類似于使用 SQL 執(zhí)行的數(shù)據(jù)庫查詢。也可以使用 Stream API 來并行執(zhí)行操作。
    簡而言之,Stream API 提供了一種高效且易于使用的處理數(shù)據(jù)的方式。

    流到底是什么呢?

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

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

      steam操作的三個(gè)步驟

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

創(chuàng)建Stream的方式

1.Java8 中的 Collection 接口被擴(kuò)展,提供了
  兩個(gè)獲取流的方法:

? default Stream<E> stream() : 返回一個(gè)順序流
? default Stream<E> parallelStream() : 返回一個(gè)并行流
2.Java8 中的 Arrays 的靜態(tài)方法 stream() 可以獲取數(shù)組流:
? static <T> Stream<T> stream(T[] array): 返回一個(gè)流
重載形式,能夠處理對(duì)應(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)建一個(gè)流。它可以接收任意數(shù)量的參數(shù)。
? public static<T> Stream<T> of(T... values) : 返回一個(gè)流
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 的中間操作

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

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

    steam的終止操作

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

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

并行流與串行流

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

列子:

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 "測(cè)試方法引用!";
}

@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 的操作三個(gè)步驟
//1. 創(chuàng)建 Stream
//一個(gè)數(shù)據(jù)源(如:集合、數(shù)組),獲取一個(gè)流
//?2. 中間操作
//一個(gè)中間操作鏈,對(duì)數(shù)據(jù)源的數(shù)據(jù)進(jìn)行處理
//?3. 終止操作(終端操作)
//一個(gè)終止操作,執(zhí)行中間操作鏈,并產(chǎn)生結(jié)果
//我們會(huì)創(chuàng)建流跟集合關(guān)聯(lián)起來,關(guān)聯(lián)起來后,我們是想要使用這個(gè)流對(duì)集合中的元素,進(jìn)行一些列的中間操作
//1. 篩選與切片
//filter(Predicate p) 過濾 接收 Lambda ,從流中排除某些元素。
//distinct() 去重,通過流所生成元素的 hashCode () 和 equals () 去除重復(fù)元素
//limit( long maxSize)截?cái)嗔?,使其元素不超過給定數(shù)量。
//skip( long n)跳過元素,返回一個(gè)扔掉了前 n 個(gè)元素的流。若流中元素不足 n 個(gè),則返回一個(gè)空流。與 limit (n) 互補(bǔ)
//

    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)
    );
    //獲取流跟集合進(jìn)行關(guān)聯(lián)
    Stream<Employee> stream = emps.stream();
    //那么我們通過這個(gè)流,對(duì)集合中的元素進(jìn)行一些列的中間操作
    //獲取工資大于6000塊錢的員工
   // Predicate<T> 斷言型接口
    Stream<Employee> employeeStream = stream.filter((employee) -> employee.getSalary()>6666);
    //終止操作沒有執(zhí)行,其實(shí)中間操作,沒有執(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); //截?cái)嗔?    //skip( long n)跳過元素,返回一個(gè)扔掉了前 n 個(gè)元素的流。若流中元素不足 n 個(gè),則返回一個(gè)空流。與 limit (n) 互補(bǔ)
    Stream<Employee> skip = stream1.skip(1);//跳過前幾個(gè)元素,留下剩下的
    skip.forEach(System.out::println);

}

}

網(wǎng)頁名稱:JDK新特性
轉(zhuǎn)載源于:http://bm7419.com/article48/jceoep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)、品牌網(wǎng)站制作、標(biāo)簽優(yōu)化服務(wù)器托管、微信小程序商城網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)