函數(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
compose
和andThen
都返回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 指定格式