Java 8 的一些新特性

函數(shù)式接口

Predicate

java.util.function.Predicate

@FunctionalInterface
public interface Predicate<T> {   
    // 函數(shù)式接口,布爾返回值
    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

Consumer

java.util.function.Consumer

@FunctionalInterface
public interface Consumer<T> {
    // 函數(shù)式接口昌屉,無返回值
    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Funcion

java.util.function.Function

@FunctionalInterface
public interface Function<T, R> {
    // 函數(shù)式接口恍涂,接受 T 為參數(shù)诬烹,返回 R
    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Supplier

java.util.function.Supplier

@FunctionalInterface
public interface Supplier<T> {
    // 函數(shù)式接口躯嫉,返回 T,無參數(shù)
    T get();
}

同時為簡單的數(shù)據(jù)類型準備了對應的函數(shù)式接口壶唤,一般是在 Predicate 加上對應的前綴崭孤,比如 double 對應的 Predicate 接口為 DoublePredicate 类嗤,

復合 Lambda 表達式

比較器

Compartor<Person> c = Comparator.comparing(Person::getName);

逆序

List<Apple> inventory = new ArrayList<>();
inventory.sort(comparing(Apple::getWeight).reversed());

比較器鏈

thenComparing ,如果對象的第一個 Compartor 比較之后是一樣的辨宠,就使用第二個 Compartor

List<Apple> inventory = new ArrayList<>();
inventory.sort(comparing(Apple::getWeight).reversed().thenComparing(Apple::getCountry));

謂詞復合

  • negate

    表示非

  • and

    表示與

  • or

    表示或

優(yōu)先級的確定遗锣,從左向右。

函數(shù)復合

  • compose

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
      Objects.requireNonNull(before);
      return (V v) -> apply(before.apply(v));
    }
    

    示例代碼

    Function<Integer, Integer> f = x -> x + 1;
    Function<Integer, Integer> g = x -> x * 2;
    Function<Integer, Integer> h = f.compose(g);
    int result = h.apply(1);
    

    運算方式:f(g(x)) = x * 2 + 1 = 1 * 2 + 1 = 3

  • andThen

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
      Objects.requireNonNull(after);
      return (T t) -> after.apply(apply(t));
    }
    

    示例代碼:

    Function<Integer, Integer> f = x -> x + 1;
    Function<Integer, Integer> g = x -> x * 2;
    Function<Integer, Integer> h = f.andThen(g);
    int result = h.apply(1);
    

    運算方式:g(f(x)) = (x * 1) * 2 = (1 + 1) * 2 = 4

    composeandThen 都返回 Function 對象嗤形,可以將其進行復合精偿。

流(Stream)

java.util.stream.Stream

定義:從支持數(shù)據(jù)處理操作的源生成的元素序列

流的特點

  • 只能遍歷一次

    流只能遍歷一次,遍歷之后,這個流就被消費掉了笔咽,不能再次使用搔预。

  • 內(nèi)部迭代

    使用 map 之類的方式進行迭代,而不是for-each 等循環(huán)方式

流操作

流操作可以分為兩大類叶组,中間操作和終端操作拯田。

  • 中間操作

    中間操作會返回另一個流,讓多個流組成一條流水線甩十,如果沒有觸發(fā)終端操作船庇,流不會執(zhí)行。

  • 終端操作

    終端操作會從流水線上生成結果侣监,其結果不再是注的值鸭轮。

流的使用

在使用流的時候,整個鏈是:

數(shù)據(jù)源 -> 中間操作 -> 終端操作

使用流

  • filter

  • distinct

  • limit

  • skip

  • map

  • flatMap

    與 map 的區(qū)別达吞,會進行打散操作

  • sorted

  • anyMatch : 有一個匹配

  • allMatch : 全部匹配

  • noneMatch : 不匹配

  • findFirst : 第一個

  • findAny : 查找任意一個

reduce(歸約)

T reduce(T identity, BinaryOperator<T> accumulator);
Optional<T> reduce(BinaryOperator<T> accumulator);
<U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner);

流的裝箱

boxed 方法可以裝一個基本類型的流裝箱成包裝類型的流

IntStream intStream = menu.stream().mapToInt(Person::getAge);
Stream<Integer> stream = intStream.boxed(); // 裝箱

構建流

由值創(chuàng)建流

Stream<String> steam = Stream.of("this is a Steam");
steam.map(String::toUpperCase).forEach(System.out::println);

使用 Stream 的表態(tài)方法 of 來創(chuàng)建流张弛。

由數(shù)組創(chuàng)建流

int[] arrays = {1, 2, 3, 4, 5, 6};
IntStream stream = Arrays.stream(arrays);
stream.map(x -> x * x).forEach(System.out::println);

文件生成流

try(Stream<String> lines =  Files.lines(Paths.get("/Users/mac/Documents/work/demo/loadbalancesuccess.zip"))) {
  lines.map(String::isEmpty)
    .forEach(System.out::println);
} catch (IOException e) {
  e.printStackTrace();
}

生成無限流

iterate

Stream.iterate(0, n -> n + 2)
  .limit(10)
  .forEach(System.out::println);

generate

Stream.generate(Math::random)
  .limit(5)
  .forEach(System.out::println);

iterate 與 generate 的區(qū)別:

  • iterate 方法接受一個初始值,依次應用在每個產(chǎn)生新值上的 Lambda

  • generate 不是依次對每個新生成的值應用函數(shù)

數(shù)據(jù)收集

收集器(Collector)

java.util.stream.Collectors

靜態(tài)導入其所有方法

  • counting

  • maxBy

  • minBy

  • summingInt

  • summingLong

  • summingDouble

  • sumWithCompensation

  • averagingInt

  • averagingLong

  • averagingDouble

  • joining

  • toList

  • toSet

  • toCollection

  • toMap

  • toConcurrentMap

分組 (group)

  • groupingBy
  • groupingByConcurrent
  • collectingAndThen

分區(qū)

  • partitioningBy

Collector 接口

Collector 接口提供自己的實現(xiàn)

// 結果容器
Supplier<A> supplier();

// 計算
BiConsumer<A, T> accumulator();

// 對結果進行合并
BinaryOperator<A> combiner();

// 最終轉(zhuǎn)換
Function<A, R> finisher();

// 返回一個 Characteristics 集合酪劫,定義了收集器的行為
Set<Characteristics> characteristics();

Characteristics

  • CONCURRENT

    accumulator 函數(shù)可以從多個線程同時調(diào)用吞鸭,且該收集器可以并行歸約流。

  • UNORDERED

    歸約結果不受流中項目的遍歷和累積順序的影響

  • IDENTITY_FINISH

    方法返回的函數(shù)是一個恒等函數(shù)覆糟,可以跳過刻剥。這種情況下,累加器對象將會直接用作歸約過程的最終結果

并行處理

第七章

日志調(diào)試

peek

Optional

創(chuàng)建 Optional 對象

  • 創(chuàng)建一個空的 optional 對象

    Optional<String> empty = Optional.empty();
    
  • 依據(jù)一個非空值創(chuàng)建 Optional

    Optional<String> obj = Optional.of("this is Optional Object");
    
  • 可接受 null 的 Optional

    String str = null;
    Optional<String> optionalStr = Optional.ofNullable(str);
    

使用 map 從 Optional 對象中撮和轉(zhuǎn)換值

String str = null;
Optional<String> optionalStr = Optional.ofNullable(str);
Optional<Integer> integer = optionalStr.map(String::length);
Integer integer1 = integer.get();
System.out.println(integer1);

使用 flatMap 鏈接 Optional 對象

使用 map 操作后滩字,如果返回的對象本身是 Optional 包裝的造虏,那么就會組成 Option<Option<?>> ,需要使用 flatMap 打散麦箍。

Optional 對象的默認行為

  • get()
  • orElse(T other)
  • orElseGet(Supplier<? extends T)
  • orElseThrow(Supplier<? extends X> exceptionSupplier)
  • ifPresent(Consumer<? super T)
方法 描述
empty 返回一個空的 Optional 實例
filter 如果值存在并且滿足提供的謂詞漓藕,就返回飲食該值的 Optional 對象,否則返回一個空的 Optional 對象
flatMap 如果人才輩出存在挟裂,就對該值提供的 mapping 函數(shù)調(diào)用享钞,返回一個 Optional 類型的值,否則就返回一個空的 Optional 對象
get 如果該值存在诀蓉,將該值用 Optional 封裝返回栗竖,否則拋出一個 NoSuchElementException 異常
ifPresent 如果值存在,就執(zhí)行使用該值的諒調(diào)用渠啤,否則什么也不做
map 如果值存在狐肢,就對該值執(zhí)行提供的 mapping 函數(shù)調(diào)用
of 將指定值用 Optional 封裝之后返回,如果該值為 null沥曹,則拋出一個 NullPointerCeption 異常
ofNullable 將指定什表 Optional 封裝之后返回份名,如果該值為 null碟联,則返回一個空的 Optional 對象
orElse 如果有值則將其返回,否則返回一個默認值
orElseGet 如果有值則將返回同窘,否則返回一個由指定的 Supplier 接口生成的值
orElseThrow 如果有值則將其返回玄帕,否則拋出一個由指定的 Supplier 接口生成的異常

CompletableFuture

創(chuàng)建 CompletableFuture 對象

public Future<Double> getPriceAsync(String product) {
  CompletableFuture<Double> futurePrice = new CompletableFuture<>();
  new Thread(() -> {                  //創(chuàng)建CompletableFuture對象部脚,它會包含計算的結果
    double price = calculatePrice(product);    //在另一個線程中以異步方式執(zhí)行計算
    futurePrice.complete(price); //需長時間計算的任務結束并得出結果時想邦,設置Future的返回值
  }).start();
  return futurePrice;    //←─無需等待還沒結束的計算,直接返回Future對象
}

異常處理委刘,使用 completeExceptionally 方法將異常從線程中傳遞出來

public Future<Double> getPriceAsync(String product) {
  CompletableFuture<Double> futurePrice = new CompletableFuture<>();
  new Thread( () -> {                  //←─創(chuàng)建CompletableFuture對象丧没,它會包含計算的結果
    try {
      double price = calculatePrice(product);    //←─在另一個線程中以異步方式執(zhí)行計算
      futurePrice.complete(price);    //←─需長時間計算的任務結束并得出結果時,設置Future的返回值
    } catch (Exception e) {
      futurePrice.completeExceptionally(e);
    }
  }).start();
  return futurePrice;    //←─無需等待還沒結束的計算锡移,直接返回Future對象
}

使用內(nèi)置的靜態(tài)方法(工廠方法)

public Future<Double> getPriceAsync1(String product) {
  return CompletableFuture.supplyAsync(() -> calculatePrice(product));
}

整合兩個 CompletableFuture

CompletableFuture<Double> futurePriceInUSD = 
  CompletableFuture.supplyAsync(() -> shop.getPrice(product))
      .thenCombine(CompletableFuture.supplyAsync(
            () ->  ExchangeService.getRate(Money.EUR, Money.USD)),
            (price, rate) -> price * rate
    );
  • thenCombine
  • thenCombineAsync

新的時間和日期 API

LocalDate呕童、LocalTime

使用 of 方法創(chuàng)建實例,靜態(tài)不可變對象

LocalDateTime

合并了 LocalDate 和 LocalTime

Instant 時間戳

Duration 淆珊、 Period

方法名 是否靜態(tài)方法 方法描述
between 創(chuàng)建兩個時間點之間的 interval
from 由一個臨時時間點創(chuàng)建interval
of 由它的組成部分創(chuàng)建 interval 的實例
parse 由字符串創(chuàng)建 interval 的實例
addTo 創(chuàng)建該 interval 的副本夺饲,并將其疊加到某個指定的 temporal 對象
get 讀取該 interval 的狀態(tài)
isNegative 檢查該 interval 是否為負值,不包含零
isZero 檢查該 interval 的時長是否為零
miuns 通過減去一定的時間創(chuàng)建該 interval 的副
multipliedBy 將 interval 的值乘以某個標量創(chuàng)建該 interval 的副本
negated 以忽略某個時長的方式去創(chuàng)建該 interval 的副本
plus 以增加某個指定的時長的方式創(chuàng)建該 interval 的副本
subtractFrom 從指定的 termporal 對象中減去該 interval

操縱施符、解析和格式化日期

方法名 是否是靜態(tài)方法 描述
from 依據(jù)傳入的 Temporal 對象創(chuàng)建對象實例
now 依據(jù)系統(tǒng)時鐘創(chuàng)建 Temporal 對象
of 由 Temporal 對象的某個部分創(chuàng)建該對象的實例
parse 由字符串創(chuàng)建 Temporal 對象的實例
atOffset 由字符串創(chuàng)建 Temporal 對象的實例
atZone 將 Temporal 對象和某個時區(qū)相結合
format 使用某個指定的格式器往声,將 Temporal 對象轉(zhuǎn)換成為字符串
get 讀取 Temporal 對象的某一部分的值
minus 創(chuàng)建 Temporal 對象的一個副本,通過將當前 Temporal 對象的值減去一定的時長創(chuàng)建該副本
plus 創(chuàng)建 Temporal 對象的一個副本戳吝,通過將當前 Temporal 對象的值加上一定的時長創(chuàng)建該副本
with 以該 Temporal 對象為模板浩销,對某些狀態(tài)進行修改創(chuàng)建該對象的副本

TemporalAdjuster

進行更加復雜的操作,可以使用重載版本的 with 方法傳遞一個更多定制化的 TemporalAdjuster 對象听哭。

方法名 描述
dayOfWeekInmonth 創(chuàng)建一個新的日期慢洋,它的值為同一個月中每一周的第幾天
firstDayOfMonth 創(chuàng)建一個新的日期,它的值為當月的第一天
firstDayOfNextMonth 創(chuàng)建一個新的日期陆盘,它的值為下月的第一天
firstDayOfNextYear 創(chuàng)建一個新的日期普筹,它的值為明年的第一天
firstDayOfYear 創(chuàng)建一個新的日期,它的值為當年的第一天
firstInMonth 創(chuàng)建一個新的日期隘马,它的值為同一個月中太防,第一個符合星期幾要求的值
lastDayOfMonth 創(chuàng)建一個新的日期,它的值為下月的最后一天
lastDayOfNextMonth 創(chuàng)建一個新的日期祟霍,它的值為下月的最后一天
lastDayofNextYear 創(chuàng)建一個新的日期杏头,它的值為明年的最后一天
lastDayOfYear 創(chuàng)建一個新的日期,它的值為今年的最后一天
lastInMonth 創(chuàng)建一個新的日期沸呐,它的值為同一個月中醇王,最后一個符合星期幾要求的值
next/previous 創(chuàng)建一個新的日期,并將其設定為日期調(diào)整后或者調(diào)整前崭添,前一個符合指定星期幾要求的日期
nextOrSame/previousOrSame 創(chuàng)建一個新的日期寓娩,并將其值設定為日期調(diào)整后或者調(diào)整前,第一個符合指定星期幾要求的日期,如果該日期已經(jīng)符合要求棘伴,直接返回該對象

以上 JDK 提供的仍然無法滿足要求寞埠,可以創(chuàng)建自己的 TemporalAdjuster

@FunctionalInterface
public interface TemporalAdjuster {
    Temporal adjustInto(Temporal temporal);
}

實現(xiàn) TemporalAdjuster 接口,然后在 adjustInto 方法中實現(xiàn)自己的邏輯焊夸。

自定義的 TemporalAdjuster 實現(xiàn)

public void testTemporalAdjuster() {
  LocalDateTime now = LocalDateTime.now();
  LocalDateTime nextYear = now.with((t) -> t.plus(1, ChronoUnit.YEARS));

  String format = now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
  System.out.println(format);

  String format1 = nextYear.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
  System.err.println(format1);
}

功能:獲取下一年的日期時間對象仁连。

DateTimeFormatter

  • 靜態(tài)常量,預定義的格式
  • ofPattern 指定格式
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末阱穗,一起剝皮案震驚了整個濱河市饭冬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌揪阶,老刑警劉巖昌抠,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鲁僚,居然都是意外死亡炊苫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門冰沙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侨艾,“玉大人,你說我怎么就攤上這事倦淀〗螅” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵撞叽,是天一觀的道長姻成。 經(jīng)常有香客問我,道長愿棋,這世上最難降的妖魔是什么科展? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮糠雨,結果婚禮上才睹,老公的妹妹穿的比我還像新娘。我一直安慰自己甘邀,他們只是感情好琅攘,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著松邪,像睡著了一般坞琴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上逗抑,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天剧辐,我揣著相機與錄音寒亥,去河邊找鬼。 笑死荧关,一個胖子當著我的面吹牛溉奕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播忍啤,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼加勤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了檀轨?” 一聲冷哼從身側(cè)響起胸竞,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤欺嗤,失蹤者是張志新(化名)和其女友劉穎参萄,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體煎饼,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡讹挎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吆玖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片筒溃。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沾乘,靈堂內(nèi)的尸體忽然破棺而出怜奖,到底是詐尸還是另有隱情,我是刑警寧澤翅阵,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布歪玲,位于F島的核電站,受9級特大地震影響掷匠,放射性物質(zhì)發(fā)生泄漏滥崩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一讹语、第九天 我趴在偏房一處隱蔽的房頂上張望钙皮。 院中可真熱鬧,春花似錦顽决、人聲如沸短条。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茸时。三九已至,卻和暖如春鸠儿,著一層夾襖步出監(jiān)牢的瞬間屹蚊,已是汗流浹背厕氨。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留汹粤,地道東北人命斧。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像嘱兼,于是被迫代替她去往敵國和親国葬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

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