函數(shù)式接口
Lambda表達(dá)式需要接口的支持汉操,并且接口的抽象方法還只能有一個(gè),要么沒法區(qū)分實(shí)現(xiàn)的是哪一個(gè)抽象方法了蒙兰。因此Lambda表達(dá)式需要函數(shù)式接口的支持搜变。
什么是函數(shù)式接口
接口中只有一個(gè)抽象方法的接口稱為函數(shù)式接口。
函數(shù)式接口可以使用一個(gè)注解@FunctionalInterface修飾愉耙,此注解可以檢查是否是函數(shù)式接口
函數(shù)式接口的使用
假設(shè)我們現(xiàn)在有一個(gè)需求:對(duì)一個(gè)數(shù)進(jìn)行運(yùn)算赌渣,什么運(yùn)算都可以坚芜。如果我們想用Lambda表達(dá)式來實(shí)現(xiàn)的話,我們就需要一個(gè)接口來支持,下面我們先寫一個(gè)MyFunction接口
@FunctionalInterface
public interface MyFunction {
public Integer getValue(Integer num);
}
然后我們需要一個(gè)運(yùn)算的方法
//運(yùn)算方法
public Integer operation(Integer num, MyFunction fun){
return fun.getValue(num);
}
測(cè)試類
@Test
public void test06(){
//平方運(yùn)算
Integer num = operation(10,(x) -> x*x);
System.out.println(num);
//加和運(yùn)算
Integer num2 = operation(100,(y) -> y+200);
System.out.println(num2);
}
執(zhí)行結(jié)果
100
300
不管是什么運(yùn)算缚忧,我們只需要關(guān)注Lambda表達(dá)式的方法體如何實(shí)現(xiàn)運(yùn)算就可以了悟泵。
Java8內(nèi)置的四大核心函數(shù)式接口
接口 | 參數(shù) | 返回 | 中文 | 實(shí)例 |
---|---|---|---|---|
Supplier | None | T | 提供者 | 工廠方法創(chuàng)建對(duì)象 |
Consumer | T | None | 消費(fèi)者 | 消費(fèi)一個(gè)數(shù)據(jù),無返回 |
Predicate | T | boolean | 判斷/謂詞 | 對(duì)指定條件進(jìn)行測(cè)試 |
Function | T | R | 函數(shù) | 根據(jù)一個(gè)參數(shù)得到另一個(gè)參數(shù)值 |
一闪水、Supplier 接口
Supplier 接口代表一個(gè)結(jié)果的提供者糕非。
Supplier 接口是用來生成數(shù)據(jù)的,數(shù)據(jù)的類型通過泛型參數(shù)給定球榆,使用 get()方法獲得返回值朽肥。
接口的源碼如下:
@FunctionalInterface
public interface Supplier<T> {
/**
* 得到一個(gè)結(jié)果,返回 T 對(duì)象
*
* @return a result
*/
T get();
}
Supplier 接口中的方法
T get() 獲得指定類型的數(shù)據(jù)
1.1芜果、將 Supplier 直接使用
案例需求:get()方法的基本使用鞠呈,在 Supplier 接口中 get 方法返回一個(gè)字符串。
案例步驟:
- 使用 Lambda 創(chuàng)建 Supplier 對(duì)象右钾,泛型類型為 String蚁吝,方法體返回一個(gè)字符串,return 可以省略。
- 調(diào)用 Supplier 的 get()方法得到字符串国撵,并打印輸出
public class LambdaTest {
public static void main(String[] args) {
//使用 Lambda 創(chuàng)建 Supplier 對(duì)象
Supplier supplier = () -> "Hello Java!";
//輸出它的值
System.out.println(supplier.get());
}
}
// 輸出
// Hello Java!
1.2背犯、將 Supplier 使用生成對(duì)象
案例需求:
下面的例子演示了如何通過調(diào)用一個(gè)靜態(tài)方法,生成一個(gè)員工對(duì)象返回山林。使用構(gòu)造方法做為 Supplier 參數(shù)的引用。
案例步驟:
- 在主類內(nèi)部創(chuàng)建一個(gè)私有的靜態(tài) Employee 對(duì)象邢羔,重寫 toString()方法驼抹,返回一個(gè)字符串:"我是員工"。
- 在 main 函數(shù)中創(chuàng)建一個(gè) Supplier 對(duì)象拜鹤,泛型類型是 Employee框冀。使用 Lambda 傳入 Supplier 對(duì)象,方法體實(shí)例化員工對(duì)象敏簿,省略 return 方法明也。
- 使用 supplier 對(duì)象的 get()方法得到員工對(duì)象
- 打印輸出員工對(duì)象
因?yàn)?Employee 對(duì)象是私有的,外部類無法直接實(shí)例化員工對(duì)象惯裕。
調(diào)用 Supplier 的 get()方法來生成員工對(duì)象温数,這樣做的目的是可以控制員工對(duì)象的生成方式,類似于工廠模式蜻势。
public class LambdaTest {
public static void main(String[] args) {
//使用 Lambda 傳入 Supplier 對(duì)象撑刺,將生成一個(gè)員工對(duì)象
//此時(shí)僅僅是實(shí)例化了接口并未執(zhí)行里面代碼
Supplier supplier = ()->new Employee();
//輸出員工對(duì)象
System.out.println(supplier.get());
}
//員工類
private static class Employee {//注意static
@Override
public String toString() {
return "我是員工";
}
}
}
// 輸出
// 我是員工
1.3、將 Supplier 做為方法的參數(shù)
需求說明:求數(shù)組中的最大值握玛,使用 Supplier 接口作為方法參數(shù)類型够傍,通過 Lambda 表達(dá)式求出 int 數(shù)組中的最大值次员。
需求分析:
- 定義整型數(shù)組 int[] arr = {12,68,10,2,99,313,46};
- 創(chuàng)建靜態(tài)方法 getMax():返回 int 類型,將 Supplier 做為參數(shù)王带,泛型類型為 Integer淑蔚,方法體調(diào)用 get()方法返回值。
- 在 main 函數(shù)中調(diào)用 getMax()方法愕撰,使用 Lambda 傳入 Supplier 對(duì)象刹衫,并且實(shí)現(xiàn)查找最大值的功能。
- 在 Lambda 表達(dá)式相當(dāng)于方法體:遍歷每個(gè)元素搞挣,比較大小带迟,找出最大值。
public class LambdaTest {
public static void main(String[] args) {
int[] arr = {12, 68, 10, 2, 99, 313, 46};
// 調(diào)用 getMax 方法獲得最大值囱桨,Lambda 相當(dāng)于方法體
int num = getMax(() -> {
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
return max;
});
//輸出最大值
System.out.println("最大值是:" + num);
}
//使用 Supplier 做為參數(shù)
public static int getMax(Supplier<Integer> supplier) {
return supplier.get();
}
}
// 輸出
// 最大值是:313
二仓犬、Consumer 接口
Consumer 接口代表接受單一的輸入變量而且沒有返回值的一類操作。 它的作用和 Supplier 相反舍肠,是消費(fèi)一個(gè)數(shù)據(jù)的搀继,消費(fèi)的數(shù)據(jù)類型需要通過泛型指定。
源代碼如下:
@FunctionalInterface
public interface Consumer<T> {
/**
* 接受 t 對(duì)象翠语,無返回值
*/
void accept(T t);
/**
* 默認(rèn)的組合方法叽躯,參數(shù)和返回值都是 Consumer 類型
* 先調(diào)用自己的 accept()方法,再調(diào)用參數(shù)的 accept()方法
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
Consumer 接口中的方法
void accept(T t) 接受對(duì)給定的參數(shù)進(jìn)行操作肌括。
Consumer 接口中的默認(rèn)方法:
default Consumer<T> andThen(Consumer<T> after)
如果一個(gè)方法的參數(shù)和返回值全都是 Consumer<T> 類型点骑,那么就可以實(shí)現(xiàn)效果:
消費(fèi)一個(gè)數(shù)據(jù)的時(shí)候,首先做一個(gè)操作谍夭,然后再做另一個(gè)操作黑滴,兩個(gè)操作依次執(zhí)行,實(shí)現(xiàn)一種組合操作紧索。而這個(gè)方法就是 Consumer 接口中的默認(rèn)方法 andThen袁辈。
2.1、直接使用 Consumer 對(duì)象
實(shí)現(xiàn)步驟:
- 使用 Lambda 創(chuàng)建 Consumer 對(duì)象齐板,直接打印傳入的字符串?dāng)?shù)據(jù)吵瞻。
- 調(diào)用 Consumer 的 accept()方法葛菇,在 accept()方法中傳入一個(gè)字符串?dāng)?shù)據(jù)甘磨。
public class LambdaTest {
public static void main(String[] args) {
//創(chuàng)建 Consumer 對(duì)象,打印傳入的變量 t
Consumer consumer = t -> System.out.println(t);
//調(diào)用 Consumer 中的方法
consumer.accept("Hello Lambda");
}
}
// 輸出
// Hello Lambda
2.2眯停、Consumer 做為參數(shù)
List 和 Set 集合中遍歷的 forEach 方法它的參數(shù)就是 Consumer济舆,請(qǐng)看下面的代碼:
案例需求:
- 創(chuàng)建一個(gè)數(shù)組,使用 Arrays.asList("孫悟空", "豬八戒", "白骨精", "嫦娥") 轉(zhuǎn)成 List 對(duì)象莺债。
- 使用 forEach 方法打印每一個(gè)元素滋觉,forEach 中使用 Lamba 表達(dá)式輸出傳入的字符串
public class LambdaTest {
public static void main(String[] args) {
//將數(shù)組轉(zhuǎn)成 List 對(duì)象
List<String> names = Arrays.asList("孫悟空", "豬八戒", "白骨精", "嫦娥");
//打印每一個(gè)字符串签夭,forEach 的參數(shù)就是 Consumer
names.forEach(t -> System.out.println(t));
}
}
// 輸出
//孫悟空
//豬八戒
//白骨精
//嫦娥
分析 forEach()方法的源代碼
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
這是定義在 java.lang.Iterable 接口中的默認(rèn)方法,參數(shù)就是 Consumer 對(duì)象椎侠,方法體內(nèi)對(duì)當(dāng)前集合使用 for遍歷第租,this 就是集合對(duì)象。每次對(duì)一個(gè)元素調(diào)用 accept()方法我纪。而我們外部調(diào)用的代碼中對(duì) accept()方法進(jìn)行了實(shí)現(xiàn)慎宾,輸出了每個(gè)元素。
public static T requireNonNull(T obj) 靜態(tài)方法浅悉,JDK7 中新增的方法趟据,判斷傳入的對(duì)象是否為 NULL,如果是 NULL 則拋出異常术健,不為 NULL 則返回對(duì)象本身汹碱。常用于方法或構(gòu)造方法中傳入對(duì)象參數(shù)的校驗(yàn)。
default Consumer<T> andThen(Consumer<? super T> after) {
//判斷 after 是否為 null
Objects.requireNonNull(after);
//先調(diào)用自己的 accept()方法荞估,再調(diào)用參數(shù)的 accept()方法
return (T t) -> { accept(t); after.accept(t); };
}
要想實(shí)現(xiàn)組合咳促,需要兩個(gè)或多個(gè) Lambda 表達(dá)式,而 andThen 的語義正是執(zhí)行“一步接一步”操作勘伺。
案例需求:將字符串 Hello 首先打印大寫的 HELLO等缀,然后打印小寫的 hello
實(shí)現(xiàn)步驟:
- 創(chuàng)建 Consumer 對(duì)象 c1,使用 Lambda 打印 s 對(duì)象的大寫
- 創(chuàng)建 Consumer 對(duì)象 c2娇昙,使用 Lambda 打印 s 對(duì)象的小寫
- c1 調(diào)用 andThen(c2)方法尺迂,再調(diào)用 accept("字符串"),完成依次的操作冒掌。
public class LambdaTest {
public static void main(String[] args) {
//打印大寫
Consumer<String> c1 = s -> System.out.println(s.toUpperCase());
//打印小寫
Consumer<String> c2 = s-> System.out.println(s.toLowerCase());
//調(diào)用方法
c1.andThen(c2).accept("Hello Consumer");
}
}
// 輸出
// HELLO CONSUMER
// hello consumer
2.3噪裕、使用 Consumer 做為參數(shù)
需求說明:
格式化打印信息,下面的字符串?dāng)?shù)組當(dāng)中存有多條信息股毫,請(qǐng)按照格式“姓名:XX膳音。性別:XX×逦埽”的格式將信息打印出來祭陷。要求將打印姓名的動(dòng)作作為第一個(gè) Consumer 接口的 Lambda 實(shí)例,將打印性別的動(dòng)作作為第二個(gè)Consumer 接口的 Lambda 實(shí)例趣席,將兩個(gè) Consumer 接口按照順序“拼接”到一起兵志。以下數(shù)組共 5 個(gè)元素,每個(gè)元素包含 2 項(xiàng)信息用逗號(hào)分隔宣肚。
String[] arr = { "張飛,男", "貂蟬,女", "曹操,男","孫尚香,女","小喬,女" };
實(shí)現(xiàn)步驟
- 創(chuàng)建靜態(tài)方法 printInfo()想罕,有 3 個(gè)參數(shù),第 1 個(gè)是需要打印的字符串?dāng)?shù)組霉涨,第 2 個(gè)是 Consumer用于打印姓名 name按价,第 3 個(gè)是 Consumer用于打印性別 gender惭适。
- 在 printInfo 方法中遍歷數(shù)組中每個(gè)元素,再調(diào)用 name.andThen(gender).accept(單個(gè)元素)
- 每調(diào)用一次 andThen()方法楼镐,在下面輸出一行橫線
- 在 main 函數(shù)中創(chuàng)建上面要遍歷的數(shù)組
- 調(diào)用 printInfo 方法癞志,傳入 3 個(gè)參數(shù),第 1 個(gè)參數(shù)是數(shù)組框产,第 2 個(gè)參數(shù)使用 Lambda 打印姓名今阳,參數(shù) s 表示數(shù)組中的每個(gè)元素。第 3 個(gè)參數(shù)使用 Lambda 打印性別茅信。
public class LambdaTest {
public static void main(String[] args) {
String[] arr = {"張飛,男", "貂蟬,女", "曹操,男","孫尚香,女"};
//這里的 s 表示數(shù)組中的每個(gè)元素
printInfo(arr,
s ->System.out.println("姓名:" + s.split(",")[0]),
s ->System.out.println("性別:" + s.split(",")[1]));
}
public static void printInfo(String[] arr, Consumer<String> name, Consumer<String> gender) {
for (String s : arr) {
name.andThen(gender).accept(s);
System.out.println("------------------");
}
}
}
三盾舌、Predicate 接口
Predicate 中文意思為謂語,"我是一個(gè)程序員"蘸鲸,"是"或"不是"就是謂語妖谴。
它代表只有一個(gè)變量的函數(shù),返回 boolean 類型酌摇。有時(shí)候我們需要進(jìn)行某種判斷膝舅,從而得到一個(gè) boolean 值的結(jié)果∫ざ啵可以使用 java.util.function.Predicate接口仍稀。
@FunctionalInterface
public interface Predicate<T> {
/**
* 抽象方法,對(duì) t 進(jìn)行測(cè)試埂息,返回 boolean 類型
*/
boolean test(T t);
/**
* 組合方法技潘,將當(dāng)前的謂語與另一個(gè)謂語進(jìn)行短路的與操作,返回一個(gè)謂語對(duì)象
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
/**
* 對(duì)當(dāng)前的謂語進(jìn)行邏輯非操作千康,返回一個(gè)謂語對(duì)象
*/
default Predicate<T> negate() {
return (t) -> !test(t);
}
/**
* 組合方法享幽,將當(dāng)前的謂語與另一個(gè)謂語進(jìn)行短路的或操作,返回一個(gè)謂語對(duì)象
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
/**
* 靜態(tài)方法拾弃,判斷 test(object)方法傳入的對(duì)象是否與參數(shù) targetRef 對(duì)象相等
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
Predicate 接口中的方法
boolean test(T t) 對(duì) t 進(jìn)行指定條件的測(cè)試豪椿,返回 boolean 類型
3.1搭盾、test()方法演示
案例需求:判斷 test("字符串")方法給定的參數(shù)長(zhǎng)度是否大于 5
案例步驟:
- 創(chuàng)建一個(gè) Predicate 謂語對(duì)象,使用 Lambda 實(shí)現(xiàn) boolean test(T t)方法
- 方法體的參數(shù)是 s滴某,返回字符串的長(zhǎng)度大于 5霎奢,省略 return 關(guān)鍵字幕侠。
- 兩次調(diào)用 test()方法看運(yùn)行結(jié)果碍彭,第 1 次使用字符串 Hello庇忌,第 2 次使用字符串 Predicate
public class LambdaTest {
public static void main(String[] args) {
//創(chuàng)建一個(gè) Predicate 謂語對(duì)象皆疹,boolean test(T t)方法接收字符串類型,返回 boolean 類型
Predicate<String> predicate = s -> s.length() > 5;
//兩次調(diào)用 test 方法看運(yùn)行結(jié)果
System.out.println("Hello 的長(zhǎng)度是否大于 5:" + predicate.test("Hello"));
System.out.println("Predicate 的長(zhǎng)度是否大于 5:" + predicate.test("Predicate"));
}
}
// 執(zhí)行結(jié)果
// Hello 的長(zhǎng)度是否大于 5:false
// Predicate 的長(zhǎng)度是否大于 5:true
3.2捎迫、默認(rèn)方法 and()
既然是條件判斷窄绒,就會(huì)存在與崔兴、或、非三種常見的邏輯關(guān)系螺戳。 其中將兩個(gè) Predicate 條件使用“與”邏輯連接起來實(shí)現(xiàn)“并且”的效果時(shí)倔幼,可以使用 default 方法 and爽待。 這個(gè)默認(rèn)方法接收一個(gè) Predicate 參數(shù)鸟款,返回一個(gè) Predicate參數(shù)何什。
其 JDK 源碼為:
/**
* 組合方法,將當(dāng)前的謂語與另一個(gè)謂語進(jìn)行短路的與操作蛛砰,返回一個(gè)謂語對(duì)象
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
and 方法演示示例:
案例需求:判斷一個(gè)字符串是否包含指定的字符串:既包含大寫“H”泥畅,又要包含大寫“W”
案例步驟:
- 創(chuàng)建 2 個(gè)需要判斷的字符串:s1="Hello world"和 s2="Hello World"
- 使用 Lambda 表達(dá)式琅翻,創(chuàng)建兩個(gè) Predicate 對(duì)象
- 判斷字符串 s 是否包含 H
- 判斷字符串 s 是否包含 W
- 調(diào)用 and 方法和 test 方法,分別輸出 s1 和 s2 的結(jié)果
public class LambdaTest {
public static void main(String[] args) {
//創(chuàng)建 2 個(gè)需要判斷的字符串
String s1 = "Hello world";
String s2 = "Hello World";
// 使用 Lambda 表達(dá)式,創(chuàng)建兩個(gè) Predicate 對(duì)象
//判斷 s 是否包含 H
Predicate<String> p1 = s -> s.contains("H");
//判斷 s 是否包含 W
Predicate<String> p2 = s -> s.contains("W");
//調(diào)用 and 方法
System.out.println(s1 + "是否包含 H 和 W:" + p1.and(p2).test(s1));
System.out.println(s2 + "是否包含 H 和 W:" + p1.and(p2).test(s2));
}
}
// 輸出結(jié)果
// Hello world是否包含 H 和 W:false
// Hello World是否包含 H 和 W:true
3.3涛浙、默認(rèn)方法 or()
與 and 的“與”類似摄欲,默認(rèn)方法 or 實(shí)現(xiàn)邏輯關(guān)系中的“或”操作胸墙。 這個(gè)默認(rèn)方法接收一個(gè) Predicate 參數(shù)我注,返回一個(gè) Predicate 參數(shù)迟隅。
JDK 源碼為:
/**
* 組合方法但骨,將當(dāng)前的謂語與另一個(gè)謂語進(jìn)行短路的或操作,返回一個(gè)謂語對(duì)象
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
or 方法演示示例:
案例需求:判斷一個(gè)字符串的長(zhǎng)度大于 10 或者小于 5
案例步驟:
- 創(chuàng)建三個(gè)字符串 s1,s2,s3 內(nèi)容如下圖
- 使用 Lambda 創(chuàng)建 2 個(gè) Predicate 接口對(duì)象奔缠,第 1 個(gè)判斷長(zhǎng)度是否大于 10,每 2 個(gè)判斷長(zhǎng)度是否小于 5
- 調(diào)用 or 和 test 方法輸出每個(gè)字符串的測(cè)試結(jié)果
public class LambdaTest {
public static void main(String[] args) {
//創(chuàng)建三個(gè)字符串
String s1 = "Hello World"; //大于 10
String s2 = "Java"; //小于 5
String s3 = "I am boy"; //既不大于 10吼野,又不小于 5
//使用 Lambda 創(chuàng)建 2 個(gè) Predicate 接口對(duì)象
Predicate<String> p1 = s -> s.length() > 10;
Predicate<String> p2 = s -> s.length() < 5;
//輸出每個(gè)字符串的測(cè)試結(jié)果
System.out.println(s1 + "=" + p1.or(p2).test(s1));
System.out.println(s2 + "=" + p1.or(p2).test(s2));
System.out.println(s3 + "=" + p1.or(p2).test(s3));
}
}
// 輸出結(jié)果
// Hello World=true
// Java=true
// I am boy=false
3.4、默認(rèn)方法 negate()
“與”瞳步、“或”已經(jīng)了解了闷哆,剩下的“非”(取反)也會(huì)簡(jiǎn)單。方法沒有參數(shù)抱怔,返回值為 Predicate。
默認(rèn)方法 negate的 JDK 源代碼為:
/**
* 對(duì)當(dāng)前的謂語進(jìn)行邏輯非操作屈留,返回一個(gè)謂語對(duì)象
*/
default Predicate<T> negate() {
return (t) -> !test(t);
}
從實(shí)現(xiàn)中很容易看出,它是執(zhí)行了 test 方法之后,對(duì)結(jié)果 boolean 值進(jìn)行“!”取反而已赠摇。
要在 test 方法調(diào)用之前調(diào)用 negate 方法固逗,正如 and 和 or 方法一樣惜傲。
案例需求:判斷年齡是否小于 18 歲,將判斷的結(jié)果取反贝攒。
案例步驟
- 創(chuàng)建 2 個(gè)整數(shù)類型的年齡盗誊,一個(gè) 25,一個(gè) 15 歲隘弊。
- 使用 Lambda 創(chuàng)建 1 個(gè) Predicate哈踱,判斷年齡小于 18 歲。
- 使用 nagate()取反以后再調(diào)用 test()方法梨熙,輸出兩個(gè)年齡的結(jié)果
public class LambdaTest {
public static void main(String[] args) {
int age1 = 25; //25 歲
int age2 = 15; //15 歲
Predicate<Integer> predicate = (a) -> a < 18; //判斷是否小于 18 歲
System.out.println(age1 + "小于 18 歲开镣,取反:" + predicate.negate().test(age1));
System.out.println(age2 + "小于 18 歲,取反:" + predicate.negate().test(age2));
}
}
// 執(zhí)行結(jié)果
// 25小于 18 歲咽扇,取反:true
// 15小于 18 歲邪财,取反:false
3.5、靜態(tài)方法 isEqual ()
Predicate 中唯一的靜態(tài)方法质欲,方法的參數(shù)是兩個(gè) Object 類型树埠,返回一個(gè) Predicate 類型。
作用:根據(jù) Objects.equals(Object, Object)方法比較兩個(gè)參數(shù)是否相等嘶伟,
一個(gè)對(duì)象通過 isEqual()傳入怎憋,另一個(gè)對(duì)象通過 test()傳入。
// java.util.Objects 類中的方法 說明
public static boolean equals(Object a,Object b)
作用:用于比較兩個(gè)對(duì)象是否相等
參數(shù):a 和 b 是要比較的兩個(gè)對(duì)象
返回:如果兩個(gè)對(duì)象相等九昧,則返回 true盛霎,否則返回 false
JDK 源代碼為:
/**
* 靜態(tài)方法,判斷 test(object)方法傳入的對(duì)象是否與參數(shù) targetRef 對(duì)象相等
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
案例需求:比較兩個(gè)字符串是否相等
案例步驟:
- 通過靜態(tài)方法 isEqual("newboy")耽装,直接返回 Predicate 對(duì)象
- 調(diào)用 Predicate 中的 test()方法傳入另兩個(gè)字符串分別比較
public class LambdaTest {
public static void main(String[] args) {
//通過靜態(tài)方法直接返回 Predicate 對(duì)象
Predicate predicate = Predicate.isEqual("newboy");
//調(diào)用 test()方法傳入另兩個(gè)字符串分別比較
System.out.println("兩個(gè)字符串是否相等:" + predicate.test("newboy"));
System.out.println("兩個(gè)字符串是否相等:" + predicate.test("NewBoy"));
}
}
// 執(zhí)行結(jié)果
// 兩個(gè)字符串是否相等:true
// 兩個(gè)字符串是否相等:false
3.6愤炸、Predicate 的應(yīng)用示例
需求說明:
集合當(dāng)中有多條“姓名+性別”的信息如下:"張飛,男", "貂蟬,女", "曹操,男","孫尚香,女","小喬,女",請(qǐng)通過 Predicate 接口的 and 組合方法掉奄,將符合要求的字符串篩選到集合 ArrayList 中规个,需要同時(shí)滿足兩個(gè)條件:
- 必須為女生
- 姓名為兩個(gè)字
開發(fā)步驟:
- 創(chuàng)建第 1 個(gè) Predicate 判斷條件:使用逗號(hào)分隔的第 0 個(gè)元素姓名長(zhǎng)度是 2
- 創(chuàng)建第 2 個(gè) Predicate 判斷條件:使用逗號(hào)分隔的第 1 個(gè)元素性別等于女
- 創(chuàng)建一個(gè)新的 List 集合凤薛,用于存儲(chǔ)過濾以后符合條件的字符串
- 使用 List 中的 forEach(Lambda)遍歷上面的原始 List 集合,使用 Predicate 中的 and 和 test 方法判斷每個(gè)元素
- 兩個(gè)條件都為真才添加到新的 List 集合中
- 創(chuàng)建第 1 個(gè) Consumer 接口诞仓,輸出使用逗號(hào)分隔的第 0 個(gè)元素姓名
- 創(chuàng)建第 2 個(gè) Consumer 接口缤苫,輸出使用逗號(hào)分隔的第 1 個(gè)元素性別
- 使用 List 中的 forEach(Lambda)遍歷,輸出過濾后的新的集合
- 使用 Consumer 接口中的 andThen 和 accept 方法墅拭,輸出每一個(gè)元素
public class LambdaTest {
public static void main(String[] args) {
//從數(shù)組中創(chuàng)建一個(gè) List 集合
List<String> list = Arrays.asList("張飛,男", "貂蟬,女", "曹操,男","孫尚香,女","小喬,女");
//創(chuàng)建第 1 個(gè) Predicate 判斷條件:使用逗號(hào)分隔的第 0 個(gè)元素姓名長(zhǎng)度是 2
Predicate<String> pname = s -> s.split(",")[0].length() ==2;
//創(chuàng)建第 2 個(gè) Predicate 判斷條件:使用逗號(hào)分隔的第 1 個(gè)元素性別等于女
Predicate<String> pgender = s-> s.split(",")[1].equals("女");
//創(chuàng)建一個(gè)新的 List 集合
List<String> infos = new ArrayList<>();
//使用 Lamba 中的 forEach()遍歷上面的 List 集合
//使用 Predicate 中的 and 和 test 方法判斷每個(gè)元素
list.forEach(s -> {
//兩個(gè)都為真才添加到集合中
if (pname.and(pgender).test(s)) {
infos.add(s);
}
});
//創(chuàng)建第 1 個(gè) Consumer 接口活玲,輸出使用逗號(hào)分隔的第 0 個(gè)元素姓名
Consumer<String> cname = s -> System.out.println("姓名:" + s.split(",")[0]);
//創(chuàng)建第 2 個(gè) Consumer 接口,輸出使用逗號(hào)分隔的第 1 個(gè)元素性別
Consumer<String> cgender = s -> System.out.println("性別:" + s.split(",")[1]);
//使用 Lamba 中的 forEach()遍歷谍婉,輸出過濾后的集合
infos.forEach(s -> {
//使用 Consumer 接口中的 andThen 和 accept 方法舒憾,每輸出一個(gè)元素隔一條線
cname.andThen(cgender).accept(s);
System.out.println("---------------");
});
}
}
// 輸出結(jié)果
姓名:貂蟬
性別:女
---------------
姓名:小喬
性別:女
---------------
四、Function 接口
Function接口:
- 根據(jù)一個(gè)參數(shù)得到另一個(gè)參數(shù)值穗熬,前面稱為計(jì)算的參數(shù)镀迂,后面稱為計(jì)算的結(jié)果。
- 有進(jìn)有出唤蔗,所以稱為“函數(shù) Function”探遵。
類似于數(shù)學(xué)中的函數(shù),通過一個(gè)變量求出另一個(gè)變量的值妓柜。如:f(x) = 2x+3
以下是它的 Java 源代碼:
// 代表通過一個(gè)變量求出另一個(gè)變量的結(jié)果的函數(shù)
@FunctionalInterface
public interface Function<T, R> {
/**
* 對(duì)給定的變量 t 進(jìn)行計(jì)算箱季,得到返回的結(jié)果 R
*/
R apply(T t);
/**
* 默認(rèn)組合方法,先計(jì)算當(dāng)前函數(shù)棍掐,再計(jì)算傳入的函數(shù)
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* 默認(rèn)組合方法藏雏,先計(jì)算傳入的函數(shù),再計(jì)算當(dāng)前函數(shù)
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* 靜態(tài)方法:總是返回它的輸入變量
*/
static <T> Function<T, T> identity() {
return t -> t;
}
}
4.1塌衰、抽象方法:apply()
是java.util.function.Function 接口中的方法
R apply(T t); 對(duì)給定的變量 t 進(jìn)行計(jì)算诉稍,得到返回的結(jié)果 R
apply 方法演示示例:
案例需求:將 Integer 類型轉(zhuǎn)換為 String 類型,并且輸出轉(zhuǎn)換以后字符串的長(zhǎng)度最疆。
- 創(chuàng)建一個(gè) Function 對(duì)象杯巨,輸入類型是整數(shù),輸出類型是字符串
- Lambda 表達(dá)式將一個(gè)整數(shù) i 轉(zhuǎn)成字符串
- 調(diào)用 apply(數(shù)字)方法得到轉(zhuǎn)換后的字符串努酸,再調(diào)用字符串的 length()方法得到長(zhǎng)度服爷,打印輸出
- 第 1 次轉(zhuǎn)換 99 這個(gè)數(shù)字,第 2 次轉(zhuǎn)換 1000 這個(gè)數(shù)字
public class LambdaTest {
public static void main(String[] args) {
//創(chuàng)建一個(gè) Function 對(duì)象
Function<Integer,String> converter = i -> Integer.toString(i);
System.out.println("99 轉(zhuǎn)成字符串的長(zhǎng)度是:" + converter.apply(99).length());
System.out.println("1000 轉(zhuǎn)成字符串的長(zhǎng)度是:" + converter.apply(1000).length());
}
}
// 輸出結(jié)果
99 轉(zhuǎn)成字符串的長(zhǎng)度是:2
1000 轉(zhuǎn)成字符串的長(zhǎng)度是:4
4.2获诈、默認(rèn)方法:andThen()
Function 接口中有一個(gè)默認(rèn)的 andThen 方法仍源,用來進(jìn)行組合操作。
先計(jì)算當(dāng)前函數(shù)舔涎,再計(jì)算傳入的函數(shù)笼踩。兩個(gè)函數(shù)依次執(zhí)行。
andThen 方法的參數(shù)是 Function 對(duì)象亡嫌,返回一個(gè) Function 對(duì)象嚎于。
JDK 源代碼:
/**
* 默認(rèn)組合方法掘而,先計(jì)算當(dāng)前函數(shù),再計(jì)算傳入的函數(shù)
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
案例需求:
連續(xù)進(jìn)行兩個(gè)操作:第 1 個(gè)操作是將字符串轉(zhuǎn)換成為 int 數(shù)字于购,第 2 個(gè)操作將轉(zhuǎn)換好的數(shù)字乘以 10袍睡。兩個(gè)操作按照前后順序組合到一起。
- 讓用戶從鍵盤輸入 1 個(gè)數(shù)字肋僧,使用字符串接收斑胜。
- 創(chuàng)建第 1 個(gè) Function 函數(shù)將字符串轉(zhuǎn)成整數(shù)
- 創(chuàng)建第 2 個(gè)函數(shù)將整數(shù)乘以 10 返回
- 調(diào)用 andThen 方法和 apply,并且輸出結(jié)果
public class LambdaTest {
public static void main(String[] args) {
//用戶輸入一個(gè)字符串
System.out.println("請(qǐng)輸入數(shù)字:");
Scanner input = new Scanner(System.in);
String str = input.nextLine();
//第 1 個(gè)函數(shù)將字符串轉(zhuǎn)成整數(shù)
Function<String,Integer> f1 = s -> Integer.parseInt(s);
//第 2 個(gè)函數(shù)將整數(shù)乘以 10 返回
Function<Integer,Integer> f2 = i -> i * 10;
//調(diào)用 andThen 方法嫌吠,并且輸出結(jié)果
System.out.println("轉(zhuǎn)成整數(shù)并乘以 10 以后的結(jié)果是:" + f1.andThen(f2).apply(str));
}
}
// 輸出結(jié)果
請(qǐng)輸入數(shù)字:
2
轉(zhuǎn)成整數(shù)并乘以 10 以后的結(jié)果是:20
4.3止潘、默認(rèn)方法:compose()
Function 中有一個(gè)與 andThen 非常類似的 compose 方法。
中文是"組成"的意思居兆,方法參數(shù)是 Function覆山,返回值是 Function竹伸,先運(yùn)行參數(shù)的 apply 方法泥栖,再調(diào)用自己的 apply 方法。
其 JDK 源代碼為:
/**
* 默認(rèn)組合方法勋篓,先計(jì)算傳入的函數(shù)吧享,再計(jì)算當(dāng)前函數(shù)
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
// 結(jié)合 andThen 方法的 JDK 源碼實(shí)現(xiàn)進(jìn)行對(duì)比,會(huì)發(fā)現(xiàn) compose 方法的參數(shù) Lamda 將會(huì)先執(zhí)行譬嚣。
所以二者只是先后順序的不同而已钢颂。
compose 方法的演示
案例需求:
創(chuàng)建兩個(gè)函數(shù)對(duì)象:1 個(gè)將字符串轉(zhuǎn)成大寫,1 個(gè)將字符串轉(zhuǎn)成小寫拜银。分別使用 andThen 和 compose 方法組合調(diào)用殊鞭,查看不同的計(jì)算結(jié)果。
開發(fā)步驟:
- 創(chuàng)建第 1 個(gè) Function尼桶,輸入輸出都是 String 類型操灿,將字符串轉(zhuǎn)成大寫。
- 創(chuàng)建第 2 個(gè) Function泵督,輸入輸出都是 String 類型趾盐,將字符串轉(zhuǎn)成小寫。
- 調(diào)用第 1 個(gè)函數(shù)的 apply 方法小腊,并且輸出值
- 調(diào)用第 2 個(gè)函數(shù)的 apply 方法救鲤,并且輸出值
- 調(diào)用 andThen 方法和 apply 方法查看運(yùn)行結(jié)果
- 調(diào)用 compose 方法和 apply 方法查看運(yùn)行結(jié)果
public class LambdaTest {
public static void main(String[] args) {
Function<String, String> f1 = s -> s.toUpperCase();
Function<String, String> f2 = s -> s.toLowerCase();
System.out.println("轉(zhuǎn)成大寫:" + f1.apply("Hello"));
System.out.println("轉(zhuǎn)成小寫:" + f2.apply("Hello"));
System.out.println("先轉(zhuǎn)成大寫,再轉(zhuǎn)成小寫:" + f1.andThen(f2).apply("Hello"));
System.out.println("先轉(zhuǎn)成小寫秩冈,再轉(zhuǎn)成大寫:" + f1.compose(f2).apply("Hello"));
}
}
// 執(zhí)行結(jié)果
轉(zhuǎn)成大寫:HELLO
轉(zhuǎn)成小寫:hello
先轉(zhuǎn)成大寫本缠,再轉(zhuǎn)成小寫:hello
先轉(zhuǎn)成小寫,再轉(zhuǎn)成大寫:HELLO
Function 的應(yīng)用示例
需求說明:請(qǐng)使用 Function 進(jìn)行函數(shù)拼接入问,按照順序執(zhí)行多個(gè)函數(shù)丹锹。
操作依次為:
- 將字符串"趙麗穎,20"截取數(shù)字年齡部分犹赖,得到字符串;
- 將上一步的字符串轉(zhuǎn)換成為 int 類型的數(shù)字卷仑;
- 將上一步的 int 數(shù)字累加 100峻村,得到結(jié)果 int 數(shù)字。
開發(fā)步驟:
- 創(chuàng)建第 1 個(gè) Function 對(duì)象锡凝,將字符串 20 取出粘昨,返回一個(gè)字符串
- 創(chuàng)建第 2 個(gè) Function 對(duì)象,將字符串轉(zhuǎn)成整數(shù)窜锯,返回整數(shù)
- 創(chuàng)建第 3 個(gè) Function 對(duì)象张肾,將整數(shù)加 100,返回計(jì)算結(jié)果4) 調(diào)用 andThen 方法 2 次锚扎,apply 方法應(yīng)用字符串:"趙麗穎,20"吞瞪,輸出結(jié)果
代碼實(shí)現(xiàn)
public class LambdaTest {
public static void main(String[] args) {
//創(chuàng)建第 1 個(gè) Function 對(duì)象,將字符串 20 取出驾孔,返回一個(gè)字符串
Function<String,String> fun1 = s -> s.split(",")[1];
//創(chuàng)建第 2 個(gè) Function 對(duì)象芍秆,將字符串轉(zhuǎn)成整數(shù),返回整數(shù)
Function<String,Integer> fun2 = s -> Integer.parseInt(s);
//創(chuàng)建第 3 個(gè) Function 對(duì)象翠勉,將整數(shù)加 100妖啥,返回計(jì)算結(jié)果
Function<Integer,Integer> fun3 = num -> num + 100;
//調(diào)用 andThen 方法 2 次,apply 方法應(yīng)用字符串对碌,輸出結(jié)果
System.out.println("計(jì)算結(jié)果:" + fun1.andThen(fun2).andThen(fun3).apply("趙麗穎,20"));
}
}
//輸出結(jié)果
計(jì)算結(jié)果:120
五荆虱、BinaryOperator 接口
BinaryOperator 表示對(duì)兩個(gè)相同類型的操作數(shù)進(jìn)行操作,產(chǎn)生相同類型的結(jié)果朽们。
接口中的方法
@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
/**
*
* 返回BinaryOperator返回根據(jù)指定的兩個(gè)元件的較小的Comparator
*
*/
public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
}
/**
*
* 返回一個(gè)BinaryOperator 怀读,它根據(jù)指定的Comparator返回兩個(gè)元素中的較大Comparator
*
*/
public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
}
}
這個(gè)接口中定義了兩個(gè)靜態(tài)方法,
BiFunction 是用于定義兩個(gè)操作符的函數(shù)接口骑脱。
BiFunction接口中的方法
@FunctionalInterface
public interface BiFunction<T, U, R> {
/**
* 傳入兩個(gè)參數(shù) t 和 u 進(jìn)行函數(shù)計(jì)算菜枷,返回計(jì)算的結(jié)果。
* 兩個(gè)參數(shù)和返回值都是同一種類型惜姐。
*
*/
R apply(T t, U u);
/**
* 返回一個(gè)組合函數(shù)犁跪,首先將該函數(shù)應(yīng)用于其輸入,然后將after函數(shù)應(yīng)用于結(jié)果歹袁。
* 如果任一函數(shù)的評(píng)估引發(fā)異常坷衍,則將其轉(zhuǎn)發(fā)給組合函數(shù)的調(diào)用者。
*
*/
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t, U u) -> after.apply(apply(t, u));
}
}
5.1条舔、方法的演示:apply()
案例需求:
使用 BinaryOperator 接口的 apply()方法枫耳,計(jì)算 2 個(gè)整數(shù)的和,并且輸出結(jié)果孟抗。
案例步驟:
- 創(chuàng)建類 Demo25BinaryOperator
- 創(chuàng)建 BinaryOperator 接口迁杨,使用 Lambda 實(shí)現(xiàn)方法钻心,方法有兩個(gè)參數(shù),返回方法的計(jì)算結(jié)果铅协。
- 調(diào)用 apply()方法傳入實(shí)際的參數(shù)捷沸,打印計(jì)算結(jié)果。
案例代碼:
public class LambdaTest {
public static void main(String[] args) {
BinaryOperator<Integer> operator = (m, n) -> m + n;
System.out.println("計(jì)算結(jié)果是:" + operator.apply(3, 5));
}
}
// 輸出結(jié)果
計(jì)算結(jié)果是:8
靜態(tài)方法
public static BinaryOperator minBy(Comparator comparator)
通過后面的 Comparator 比較器判斷狐史,返回兩個(gè)元素中較小的元素
public static BinaryOperator maxBy(Comparator comparator)
通過后面的 Comparator 比較器判斷痒给,返回兩個(gè)元素中較大的元素
Comparator 接口中的靜態(tài)方法說明
naturalOrder() 按元素的自然排序的大小進(jìn)行比較,返回一個(gè) Comparator 對(duì)象
reverseOrder() 按元素的倒序大小進(jìn)行比較骏全,返回一個(gè) Comparator 對(duì)象
5.2苍柏、BinaryOperator 接口做為方法參數(shù)
案例需求:
有如下數(shù)組{2,1,3,5},對(duì)數(shù)組中的每個(gè)元素進(jìn)行替換姜贡。替換算法如下:
- 第 0 個(gè)元素不變
- 第 0 個(gè)+第 1 個(gè)元素的結(jié)果代替第 1 個(gè)元素
- 第 1 個(gè)新元素+第 2 個(gè)元素的結(jié)果代替 2 個(gè)
- 第 2 個(gè)新元素+第 3 個(gè)元素的結(jié)果代替第 3 個(gè)
- 依次類推试吁,直到所有的元素替換完成為止。
//Arrays 類中的方法說明
void parallelPrefix(T[] array, BinaryOperator op)
作用:對(duì)數(shù)組中每個(gè)元素使用指定的二元操作函數(shù)進(jìn)行替換操作楼咳,并行累積
參數(shù) 1:要替換的數(shù)組
參數(shù) 2:指定二元操作函數(shù)
案例步驟
- 創(chuàng)建 BinaryOperator對(duì)象熄捍,指定 2 個(gè)數(shù)的算法是 m+n
- 創(chuàng)建 Integer 類型的數(shù)組:{2,1,3,5}
- 輸出操作前的數(shù)組
- 調(diào)用上面的 parallelPrefix()方法,將 BinaryOperator 做為參數(shù)傳入
- 輸出操作后的數(shù)組
- 如果使用不同的算法爬橡,則每個(gè)元素的替換的結(jié)果不同治唤。如:換成兩個(gè)數(shù)相乘棒动。
案例代碼
public class LambdaTest {
public static void main(String[] args) {
BinaryOperator<Integer> operator = (m,n) -> m+n;
Integer [] arr = {2,1,3,5};
System.out.println("操作前的數(shù)組:" + Arrays.toString(arr)) ;
Arrays.parallelPrefix(arr,operator);
System.out.println("操作后的數(shù)組:" + Arrays.toString(arr)) ;
}
}
//輸出結(jié)果
操作前的數(shù)組:[2, 1, 3, 5]
操作后的數(shù)組:[2, 3, 6, 11]
5.3糙申、靜態(tài)方法的演示
案例需求:
比較兩個(gè)整數(shù),使用 minBy 靜態(tài)方法找出最小值比較兩個(gè)字符串船惨,使用 maxBy 靜態(tài)方法找出最大值
案例步驟
- 創(chuàng)建 BinaryOperator對(duì)象柜裸,使用 minBy()靜態(tài)方法,按數(shù)字的正常大小進(jìn)行比較粱锐。
- 輸出最小值疙挺,調(diào)用 apply()方法,傳入 2 個(gè)整數(shù)怜浅。
- 創(chuàng)建 BinaryOperator對(duì)象铐然,使用 maxBy()靜態(tài)方法,按字符串的大小進(jìn)行比較恶座。
- 輸出最大值搀暑,調(diào)用 apply()方法,傳入 2 個(gè)字符串:"ABCD","xyz"
案例代碼
public class LambdaTest {
public static void main(String[] args) {
//naturalOrder()是 Comparator 中的靜態(tài)方法跨琳,即按數(shù)字的正常大小進(jìn)行比較
BinaryOperator oper1 = BinaryOperator.minBy(Comparator.naturalOrder());
System.out.println("最小值是:" + oper1.apply(3,5));
//naturalOrder()是 Comparator 中的靜態(tài)方法自点,即按字符串的正常大小進(jìn)行比較
BinaryOperator oper2 = BinaryOperator.maxBy(Comparator.naturalOrder());
System.out.println("最大值是:" + oper2.apply("ABCD","xyz"));
}
}
// 輸出結(jié)果
最小值是:3
最大值是:xyz
六、UnaryOperator 接口
UnaryOperator 表示對(duì)單個(gè)操作數(shù)的操作脉让,該操作數(shù)生成與其操作數(shù)類型相同的結(jié)果桂敛。
UnaryOperator 接口繼承于 Function 接口功炮,
所以有 T apply(T t)抽象方法,與前面的 Function 接口中的 apply()方法相同术唬。
它的輸入類型和返回類型是相同的類型薪伏。
UnaryOperator 接口的源碼
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
/**
* 始終返回其輸入?yún)?shù)的一元運(yùn)算符
*/
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}
方法的演示
UnaryOperator 接口中的方法說明
T apply(T t);
從 Function 接口中繼承下來的抽象方法,使用給定的參數(shù)應(yīng)用此一元運(yùn)算函數(shù)粗仓,返回另一個(gè)值毅该。
參數(shù)和返回值是同一種類型。
static UnaryOperator identity()
始終返回其輸入?yún)?shù)的一元運(yùn)算符也就是后續(xù) apply()輸入的是什么潦牛,就返回什么眶掌。
案例步驟
- 使用 UnaryOperator.identity()靜態(tài)方法創(chuàng)建 UnaryOperator對(duì)象
- 應(yīng)用 apply()方法,輸入字符串 abc巴碗,得到結(jié)果也是 abc朴爬。
public class LambdaTest {
public static void main(String[] args) {
//創(chuàng)建一個(gè) UnaryOperator對(duì)象,
UnaryOperator operator = UnaryOperator.identity();
//調(diào)用 apply()方法橡淆,輸出參數(shù)的值
System.out.println("輸出與輸入一樣:" + operator.apply("abc"));
}
}
//輸出結(jié)果
輸出與輸入一樣:abc
UnaryOperator 使用方法的參數(shù)
案例需求:
有一個(gè)整數(shù)的列表集合召噩,將集合中每個(gè)元素乘以 2,再替換這個(gè)元素逸爵,輸出替換前后的列表集合有一個(gè)字符串的列表集合具滴,將集合中每個(gè)元素用它的大寫進(jìn)行替換。
ArrayList 中的方法說明
replaceAll(UnaryOperator operator)
使用一元操作函數(shù)的結(jié)果师倔,替換列表中的每個(gè)元素
案例步驟:
- 使用 Arrays.asList()創(chuàng)建一個(gè)整數(shù)列表
- 創(chuàng)建 UnaryOperator一元運(yùn)算函數(shù)构韵,指定運(yùn)算表達(dá)式是 x*2
- 調(diào)用 ArrayList 的 replaceAll()方法,把上面創(chuàng)建的一元運(yùn)算函數(shù)做為參數(shù)傳入
- 輸出替換前后的列表
- 使用 Arrays.asList()創(chuàng)建一個(gè)字符串列表
- 這次直接在 replaceAll()方法中傳入 Lambda 表達(dá)式趋艘,s.toUpperCase()
- 輸出替換前后的列表
public class LambdaTest {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(3, 10, 8, 2);
System.out.println("替換前:" + nums);
UnaryOperator<Integer> oper = x -> x * 2;
nums.replaceAll(oper);
System.out.println("替換后:" + nums);
List<String> names = Arrays.asList("Jack","Rose","Tom","NewBoy");
System.out.println("替換前:" + names);
names.replaceAll(s -> s.toUpperCase());
System.out.println("替換后:" + names);
}
}
//輸出
替換前:[3, 10, 8, 2]
替換后:[6, 20, 16, 4]
替換前:[Jack, Rose, Tom, NewBoy]
替換后:[JACK, ROSE, TOM, NEWBOY]
七疲恢、常用的函數(shù)式接口小結(jié)
1、Supplier 提供數(shù)據(jù)者
T get();沒有傳入?yún)?shù)瓷胧,有結(jié)果显拳。
2、Consumer 消費(fèi)數(shù)據(jù)者
void accept(T t); 傳入數(shù)據(jù)搓萧,沒有結(jié)果杂数。
andThen()
3、Predicate 謂語
boolean test(T t); 對(duì)傳入的數(shù)據(jù)邏輯判斷
and()
or()
negate()
isEqual()
4瘸洛、Function 函數(shù)
R apply(T t); 傳入一個(gè)變量返回計(jì)算結(jié)果
andThen()
compose()
identity()
5揍移、BinaryOperator 二元操作符
T apply(T t,T u); 傳入兩個(gè)參數(shù)返回一個(gè)結(jié)果
andThen()
繼承于 BiFunction
6、UnaryOperator
繼承于 Function
一元操作符
T apply(T t); 傳入一個(gè)參數(shù)返回一個(gè)結(jié)果
andThen()
compose()
identity()
參考:
https://blog.csdn.net/swadian2008/article/details/119780384