天天看點

JDK新特性JDK1.5新特性JDK1.7新特性JDK1.8新特性Stream API

枚舉概述: 就是一個類隻能存在幾個固定的對象,那麼這個就是枚舉.我們就可以使用這些對象可以表示一些固定的值.

舉例:一周隻有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(front.name());

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

System.out.println(front);

// <T> T valueOf(Class<T> type,String name): 用來擷取指定的枚舉項

// type: 表示的是對應的枚舉的位元組碼檔案對象

// name: 就是枚舉項的名稱

Direction direction = Direction.valueOf(Direction.class, "RIGHT") ;

System.out.println(direction);

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 {

Direction front = Direction.FRONT;

Direction after = Direction.AFTER;

Direction left = Direction.LEFT;

Direction right = Direction.RIGHT;

System.out.println(after);

System.out.println(left);

System.out.println(right);

為了增強對數值的閱讀性,如我們經常把資料用逗号分隔一樣。JDK7提供了_對資料分隔。

舉例:

int x = 100_1000;

注意事項:

不能出現在進制辨別和數值之間

不能出現在數值開頭和結尾

不能出現在小數點旁邊

LocalDate、 LocalTime、 LocalDateTime類的執行個體是不可變的對象,分别表示使用 ISO-8601月曆系統的日期、時間、日期和時間它們提供了簡單的日期或時間,并不包含目前的時間資訊。也不包含與時區相關的資訊。

注: ISO-8601月曆系統是國際标準化組織制定的現代公民的日期和時間的表示法

這些新增的日期時間API都在 java.time包下

1通過靜态方法 now();

例如:LocalDateTime ldt = LocalDateTime.now();

1擷取對象的方法 now()

注意預設擷取出來的是目前的美國時間和我們相差八個小時

Instant ins = Instant.now();

System.out.println(ins);

我們在東八區 是以可以加8個小時 就是我們的中原標準時間

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();

ofEpochSecond()方法 給計算機元年增加秒數

例如 Instant instant = Instant.ofEpochSecond(5);

System.out.println(instant);

機關換算

0.1 毫秒 = 10 的5次方納秒 = 100000 納秒

1 毫秒 = 1000 微妙 = 1000000 納秒

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());間隔多少天

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

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

});

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方法 傳入一個日期格式化類對象

4.使用自定義的日期格式格式化字元串

DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");//自定義一個日期格式

String time = now1.format(timeFormat);

把一個日期字元串轉成日期對象

使用日期類中的parse方法傳入一個日期字元串,傳入對應的日期格式化類

LocalDateTime parse = LocalDateTime.parse(time, timeFormat);

System.out.println(parse);

用法和 LocalDate、 LocalTime、 LocalDateTime 一樣 隻不過ZonedDate,ZonedTime、ZonedDateTime 這三個帶有目前系統的預設時區

1.擷取世界各個地方的時區的集合 的方法getAvailableZoneIds()

使用ZoneID中的靜态方法getAvailableZoneIds();來擷取

例如:Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();

2.擷取系統預設時區的ID

ZoneId zoneId = ZoneId.systemDefault(); //Asia/Shanghai

3.擷取帶有時區的日期時間對象

//建立日期對象

//擷取不同國家的日期時間根據各個地區的時區ID名建立對象

ZoneId timeID = ZoneId.of("Asia/Shanghai");

//根據時區ID擷取帶有時區的日期時間對象

ZonedDateTime time = now.atZone(timeID);

//方式2 通過時區ID 擷取日期對象

LocalDateTime now2 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));

System.out.println(now2);

Lambda 是一個匿名函數,我們可以把 Lambda表達式了解為是一段可以傳遞的代碼(将代碼像資料一樣進行傳遞)。可以寫出更簡潔、更靈活的代碼。作為一種更緊湊的代碼風格,使Java的語言表達能力得到了提升。

public interface MyInterface {

void show(int a,int b);

//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);

public class MyTest2 {

MyInterface2 myInterface2 = new MyInterface2() {br/>@Override

public int test(int a, int b) {

return a + b;

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();

new MyInteface3(){br/>@Override

public void test() {

//Lambda 需要 函數式接口的支援

// 函數式接口:這個接口中,僅僅隻有 一個抽象方法

// 函數式接口可以使用注解 @FunctionalInterface 來檢測這個接口是不是函數式接口

public class MyTest3 {

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

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

你可以通過 Lambda 表達式來建立該接口的對象

我們可以在任意函數式接口上使用 @FunctionalInterface 注解,這樣做可以檢查它是否是一個函數式接口,同時 javadoc 也會包含一條聲明,說明這個接口是一個函數式接口.

函數式接口 參數類型 傳回類型 用途

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

double R 參數分别為int、 long、

double 類型的函數

Stream 是 Java8 中處理集合的關鍵抽象概念,

它可以指定你希望對集合進行的操作,

可以執行非常複雜的查找、過濾和映射資料等操作。

使用Stream API 對集合資料進行操作,就類似于使用 SQL 執行的資料庫查詢。也可以使用 Stream API 來并行執行操作。

簡而言之,Stream API 提供了一種高效且易于使用的處理資料的方式。

是資料管道,用于操作資料源(集合、數組等)所生成的元素序列。

集合講的是資料,流講的是計算!

注意:

①Stream 自己不會存儲元素。

②Stream 不會改變源對象。相反,他們會傳回一個持有結果的新Stream。

③Stream 操作是延遲執行的。這意味着他們會等到需要結果的時候才執行。

Stream 的操作三個步驟

1.建立 Stream

一個資料源(如:集合、數組),擷取一個流

 2.中間操作

一個中間操作鍊,對資料源的資料進行處理

 3.終止操作(終端操作)

一個終止操作,執行中間操作鍊,并産生結果

 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) 生成

篩選與切片

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) 産生一個新流,其中按比較器順序排序 傳入一個比較器

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

并行流就是把一個内容分成多個資料塊,并用不同的線程分别處理每個資料塊的流。

Java 8 中将并行進行了優化,我們可以很容易的對資料進行并行操作。

Stream API 可以聲明性地通過 parallel() 與sequential() 在并行流與順序流之間進行切換。

public Employee() {

//**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(105, "田七", 38, 5555.55)

);

new Employee(104, "趙六", 8, 7777.771),

new Employee(104, "趙六", 8, 7777.772),

new Employee(104, "趙六", 8, 7777.773),

繼續閱讀