java8簡記

使用java8有一段時間了, 簡單記錄一下

Lambda

Lambda類似于匿名內(nèi)部類,一個簡單的小栗子:

new Thread(() -> {
            System.out.println("hello, Lambda");
        }).start();

可以看到使用Lambda更簡潔

lambda表達(dá)式和內(nèi)部類有點類似,可以訪問類屬性,final方法局部變量.
注意 :更改lambda表達(dá)式中的變量不是線程安全的.
對于只包含一個抽象方法的接口, 可以通過lambda表達(dá)式創(chuàng)建該接口對象.這種接口稱為函數(shù)式接口.
(接口可以重新聲明Object類的方法,如ToString, clone, equals, 這些不是抽象方法, java8的default方法也不是) :

Comparator<Integer> c = (final Integer t1, final Integer t2) -> {return Integer.compare(t1, t2);};

上面栗子中, final是為了演示添加的,可以省略, 參數(shù)類型Integer java可以推導(dǎo)出來.
方法體中, 因為只要一句代碼,所以return和{}可以省略

Comparator<Integer> c = (t1, t2) ->  Integer.compare(t1, t2);

甚至是

Comparator<Integer> c = Integer::compare;

上面使用了方法引用, 使用::操作符引用一個方法敬惦,有三種方式

  • 類::靜態(tài)方法, 調(diào)用參數(shù)作為靜態(tài)方法的參數(shù) Integer::parseInt 等價于 s -> Integer.parseInt(s) , 對象對象s作為parseInt參數(shù)
  • 類::實例方法, 第一個參數(shù)就是執(zhí)行方法的對象 Object::toString 等價于 o -> o.toString(), 直接調(diào)用調(diào)用對象o的toString方法
  • 構(gòu)造方法

java8提供了許多常用的函數(shù)式接口


這些函數(shù)式接口可以作為類屬性,方法參數(shù),甚至返回值
如, 提供一個解析xml的接口, 由用戶判斷一個節(jié)點是否要處理, 如果要處理, 就交由用戶進(jìn)行處理. 可以使用如下方法定義:

public void handle(Predicate<Node> p, Consumer<Node> c)

而不用只定義NodeCheck, NodeHanler等接口

Optional

使用Optional可以有效的減小null的判斷,特別是map的取值谣拣,如從一個Map<String, Object> map獲取"amount"的值并轉(zhuǎn)化為int(假定map或map.get("amount")都可能為null),
以往的寫法:

    Integer i = null;
    Object o = map.get("amount");
    if(o != null) {
        String s = o.toString();
        if(s != null) {
            i = Integer.parseInt(s);
        }
    }

而使用Optional則非常簡潔

Integer i = optional.map(k -> k.get("amount")).map(o -> o.toString()).map(s -> Integer.parseInt(s)).orElse(null);

參考: 使用 Java8 Optional 的正確姿勢

個人覺得:雖然Optional使用方便,但始終覺得方法定義Optional<User> getUser(String code)
沒有User getUser(String code)直觀

stream

對于stream, 先來看個小栗子, 對一個List<Integer> list, 過濾掉其中的奇數(shù):

list  = list.stream().filter(i -> i % 2 == 0).collect(Collectors.toList());

上面栗子中尝江,可以分為3步:

  1. list.stream()創(chuàng)建一個stream
  2. filter(Predicate<? super T> predicate)進(jìn)行過濾操作, 僅保留predicate返回true的元素
  3. collect(Collector<? super T, A, R> collector)進(jìn)行結(jié)果收集

除了filter, java8還提供了常用的元素處理方案:

  • map 對stream中元素的類型轉(zhuǎn)換
  • limit 取前n個元素
  • skip 丟棄前n個元素
  • distinct 丟棄重復(fù)的方法
  • sort 排序

收集結(jié)果

  • toArray 到數(shù)組
  • collect(Collectors.toList()) 到List
  • collect(Collectors.toMap) 到Map

還有其他的聚合方案

  • count
  • max
  • min
  • findFirst
  • findAny
  • allMatch
  • noneMatch

還可以使用stream分組
對于上個栗子中的list, 現(xiàn)在按奇偶數(shù)分成兩組:

Map<Boolean, List<Integer>> oddMap = list.stream().collect(Collectors.partitioningBy(i -> i % 2 == 0));

根據(jù)屬性分組

Map<String, List<User>> cityGroup = list.stream().collect(Collectors.groupingBy(User::getCity));

這是個很有用的特性, 因為我們常常要進(jìn)行分組操作出嘹, 如對于一組user, 可以按地區(qū), 用戶等級等屬性進(jìn)行分組.

注意
可以很方便將list轉(zhuǎn)成map

Map<String, User> users = userList.stream().collect(Collectors.toMap(User::getCode, c -> c)); 

但如果userList中用兩個User.getCode()返回結(jié)果相同, 則會拋出異常java.lang.IllegalStateException: Duplicate key 1
可以使用userList.stream().collect(Collectors.toMap(User::getCode, c -> c, (a, b) -> a))解決這個問題,它表示凭需,當(dāng)兩個User.getCode()結(jié)果相同時辙谜,取第一個User俺榆。

時間api

java8還有個比較大的改動,就是時間API筷弦。
java8加入了LocalDate和LocalTime肋演, 它們使用的是ISO8601標(biāo)準(zhǔn)時間格式,和時區(qū)無關(guān)烂琴,和unix時間戳類似.
unix時間戳表示從1970年1月1日(UTC/GMT的午夜)開始所經(jīng)過的秒數(shù)。 也是說, 一個unix時間戳n蜕乡, 對于每個地區(qū)奸绷, 它都表示該地區(qū)從1970年1月1日(UTC/GMT的午夜)開始經(jīng)過n秒后的時間。
如1507564800表示2017/10/10 00:00:00, 如果在北京, 則表示北京時間2017/10/10 00:00:00, 如果在倫敦, 則表示倫敦時間2017/10/10 00:00:00(北京時間和倫敦時間時差八小時, 此時北京時間是2017/10/10 08:00:00)
LocalDate和LocalTime同理层玲。

// 當(dāng)前時間
LocalDate now = LocalDate.now();
// 當(dāng)前時間加一天号醉, 并按常用格式y(tǒng)yyy-MM-dd格式化
now.plusDays(1).format(DateTimeFormatter.BASIC_ISO_DATE);
// 當(dāng)前時間減一天, 并按指定格式格式化
now.minusMonths(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

// 字符串轉(zhuǎn)時間
LocalDate date = LocalDate.parse("2019-01-26", DateTimeFormatter.ISO_DATE);
// 時間比較
now.isAfter(date);

LocalDate與Date轉(zhuǎn)換

// 時區(qū)ZoneId LocalDate時區(qū)不相關(guān), Date時區(qū), 兩者轉(zhuǎn)化需使用ZoneId
ZoneId zoneId = ZoneId.systemDefault();

LocalDate localDate = LocalDate.now();
// localDate轉(zhuǎn)ZonedDateTime
ZonedDateTime zdt = localDate.atStartOfDay(zoneId);
// ZonedDateTime轉(zhuǎn)Date
Date date = Date.from(zdt.toInstant());

Date nowDate = new Date();
// Instant:nanosecond表示的時間戳
Instant instant = nowDate.toInstant();
// instant轉(zhuǎn)ZonedDateTime
ZonedDateTime nowZonedDate = instant.atZone(zoneId);
// ZonedDateTime轉(zhuǎn)LocalDate
LocalDate nowLocalDate = nowZonedDate.toLocalDate();

java7的新特性

簡單記錄一下java7比較重要的新特性

Path

java7新增了Path類, 可以便捷的對目錄進(jìn)行操作
當(dāng)前resources目錄結(jié)構(gòu)為

|-- resources
    |-- local.properties
    |-- xml
        |-- local.xml

看一個小栗子

@Test
public void testPath() throws URISyntaxException {
    // 獲取local.properties文件
    URI localProUri = this.getClass().getClassLoader().getResource("local.properties").toURI();

    // 轉(zhuǎn)換為Path對象, 指向 .../resources/test/local.properties
    Path localProPath = Paths.get(localProUri);

    // 解析localProPath兄弟目錄, 指向 .../resources/test/xml
    Path xmlPath = localProPath.resolveSibling("xml");

    // 解析xmlPath目錄目錄, 指向 .../resources/test/xml/local.xml
    Path localXmlPath = xmlPath.resolve("local.xml");

    // 轉(zhuǎn)換為絕對路徑
    localXmlPath.toAbsolutePath();

    // 獲取文件名
    localXmlPath.getFileName();
    
    // 獲取根目錄
    localXmlPath.getRoot();
    
    // 獲取父目錄
    localXmlPath.getParent();
}

Files

java7也新增了Files類辛块, 可以對文件進(jìn)行讀取畔派,寫入, 復(fù)制润绵,移動等操作


@Test
public void testFileRead() throws URISyntaxException, IOException {
    Path localProPath = Paths.get(this.getClass().getClassLoader().getResource("local.properties").toURI());
    // 讀取文件中所以的字節(jié)
    byte[] localProBytes = Files.readAllBytes(localProPath);
}


@Test
public void testFileCopy() throws URISyntaxException, IOException {
    Path localProPath = Paths.get(this.getClass().getClassLoader().getResource("local.properties").toURI());
    // 復(fù)制文件, StandardCopyOption.REPLACE_EXISTING表示替換已存在的文件
    Path targetPath = Files.copy(localProPath, localProPath.getParent().resolve("dev.properties"), StandardCopyOption.REPLACE_EXISTING);
}

@Test
public void testAppend() throws URISyntaxException, IOException {
    Path localProPath = Paths.get(this.getClass().getClassLoader().getResource("local.properties").toURI());

    // 追加文件,StandardOpenOption.APPEND表示追加
    Files.write(localProPath, "group=local".getBytes(), StandardOpenOption.APPEND);
}

這個有點類似于org.apache.commons.io.FileUtils類了线椰。

try-with-resources

AutoCloseable是java7添加的接口, 實現(xiàn)了該接口的資源類可以使用try-with-resources語法

try (InputStream inputStream = new FileInputStream("local.properties")) {
    ...
} catch (IOException e) {
    e.printStackTrace();
}

對比一下原來的寫法

InputStream inputStream = null;
try {
     inputStream = new FileInputStream("local.properties");
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if(inputStream != null) {
        try {
            inputStream.close();
        } catch (IOException e) {
        }
    }
}

捕獲多個異常

java7中可以在同一個catch分支中捕獲多個異常類型尘盼。引用《寫給大忙人看的JavaSE8》中的一個栗子:

try {
    ...
} catch(FileNotFoundException | UnknownHostException ex) {
    // 處理丟失文件和未知主機的異常
} catch() {
    // 處理所有的IO異常
}

Objects

java7新增了Objects類憨愉, 提供一些常用的Object操作, 如deepEquals卿捎,isNull配紫,nonNull,requireNonNull等午阵。

參考:
Java8學(xué)習(xí)筆記
《寫給大忙人看的Java SE 8》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末躺孝,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌植袍,老刑警劉巖伪很,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異奋单,居然都是意外死亡锉试,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進(jìn)店門览濒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呆盖,“玉大人,你說我怎么就攤上這事贷笛∮τ郑” “怎么了?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵乏苦,是天一觀的道長株扛。 經(jīng)常有香客問我,道長汇荐,這世上最難降的妖魔是什么洞就? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮掀淘,結(jié)果婚禮上旬蟋,老公的妹妹穿的比我還像新娘。我一直安慰自己革娄,他們只是感情好倾贰,可當(dāng)我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拦惋,像睡著了一般匆浙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上厕妖,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天首尼,我揣著相機與錄音,去河邊找鬼叹放。 笑死饰恕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的井仰。 我是一名探鬼主播埋嵌,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼俱恶!你這毒婦竟也來了雹嗦?” 一聲冷哼從身側(cè)響起范舀,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎了罪,沒想到半個月后锭环,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡泊藕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年辅辩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娃圆。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡玫锋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出讼呢,到底是詐尸還是另有隱情撩鹿,我是刑警寧澤,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布悦屏,位于F島的核電站节沦,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏础爬。R本人自食惡果不足惜甫贯,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望幕帆。 院中可真熱鬧获搏,春花似錦、人聲如沸失乾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碱茁。三九已至,卻和暖如春仿贬,著一層夾襖步出監(jiān)牢的瞬間纽竣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工茧泪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蜓氨,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓队伟,卻偏偏與公主長得像穴吹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嗜侮,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容

  • Java8 in action 沒有共享的可變數(shù)據(jù)港令,將方法和函數(shù)即代碼傳遞給其他方法的能力就是我們平常所說的函數(shù)式...
    鐵牛很鐵閱讀 1,223評論 1 2
  • Java 8自Java 5(發(fā)行于2004)以來最具革命性的版本啥容。Java 8 為Java語言、編譯器顷霹、類庫咪惠、開發(fā)...
    誰在烽煙彼岸閱讀 887評論 0 4
  • Java 8自Java 5(發(fā)行于2004)以來最具革命性的版本。Java 8 為Java語言淋淀、編譯器遥昧、類庫、開發(fā)...
    huoyl0410閱讀 620評論 1 2
  • 對于Java開發(fā)者來說朵纷,Java8的版本顯然是一個具有里程碑意義的版本炭臭,蘊含了許多令人激動的新特性,如果能利用好這...
    jackcooper閱讀 1,020評論 0 6
  • DOM 當(dāng)網(wǎng)頁被加載時柴罐,瀏覽器會創(chuàng)建頁面的文檔對象模型(Document Object Model)徽缚。通過 HTM...
    MA木易YA閱讀 227評論 0 0