枚舉概述: 就是一個類隻能存在幾個固定的對象,那麼這個就是枚舉.我們就可以使用這些對象可以表示一些固定的值.
舉例:一周隻有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),