最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 中的 Function 接口案例講解

 更新時間:2025年06月21日 15:06:58   作者:apeiMark  
Java8引入Function和Consumer函數(shù)式接口,用于處理輸入輸出及單參數(shù)操作,支持基本類型和多參數(shù)變體,應(yīng)用于StreamAPI、策略模式及異常處理包裝,提升代碼簡潔性與性能,本文給大家介紹Java中的Function接口案例,感興趣的朋友一起看看吧

Function 是 Java 8 引入的一個核心函數(shù)式接口,屬于 java.util.function 包。它代表一個"接受一個參數(shù)并產(chǎn)生結(jié)果"的函數(shù)。

1. Function 的基本概念

1.1. 定義

T:輸入類型(參數(shù)類型)

R:結(jié)果類型(返回類型)

唯一抽象方法:R apply(T t)

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
    // 還包含兩個默認方法(后面會講解)
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before)
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after)
}

1.2. 基本用法示例

// 1. 定義一個將字符串轉(zhuǎn)為長度的函數(shù)
Function<String, Integer> lengthFunction = s -> s.length();
System.out.println(lengthFunction.apply("Hello")); // 輸出 5
// 2. 定義將數(shù)字轉(zhuǎn)為字符串的函數(shù)
Function<Integer, String> stringify = num -> "Number: " + num;
System.out.println(stringify.apply(42)); // 輸出 "Number: 42"

2. Function 的方法詳解

// 1. apply(T t)
// 核心方法,執(zhí)行函數(shù)轉(zhuǎn)換:
Function<String, String> upperCase = s -> s.toUpperCase();
String result = upperCase.apply("hello"); // 返回 "HELLO"
-------------------------------------------------------------------------
// 2. compose(Function before)
// 組合函數(shù),先執(zhí)行 before 函數(shù),再執(zhí)行當(dāng)前函數(shù):
Function<Integer, String> intToStr = i -> "Value: " + i;
Function<String, Integer> strToInt = s -> Integer.parseInt(s);
// 先執(zhí)行 strToInt,再執(zhí)行 intToStr
Function<String, String> composed = intToStr.compose(strToInt);
System.out.println(composed.apply("123")); // 輸出 "Value: 123"
-------------------------------------------------------------------------
// 3. andThen(Function after)
// 組合函數(shù),先執(zhí)行當(dāng)前函數(shù),再執(zhí)行 after 函數(shù):
Function<String, Integer> parse = Integer::parseInt;
Function<Integer, Integer> square = i -> i * i;
// 先執(zhí)行 parse,再執(zhí)行 square
Function<String, Integer> parseThenSquare = parse.andThen(square);
System.out.println(parseThenSquare.apply("5")); // 輸出 25
-------------------------------------------------------------------------	
// 4. identity()
// 靜態(tài)方法,返回一個總是返回其輸入?yún)?shù)的函數(shù):
Function<String, String> identity = Function.identity();
System.out.println(identity.apply("Same")); // 輸出 "Same"
-------------------------------------------------------------------------

3. Function 的變體

Java 還提供了 Function 的一些特化版本:

3.1. 基本類型特化

接口 方法簽名 等價于

IntFunction<R> R apply(int value) Function<Integer, R>

DoubleFunction<R> R apply(double value) Function<Double, R>

LongFunction<R> R apply(long value) Function<Long, R>

IntFunction<String> intToString = i -> "Num: " + i;
System.out.println(intToString.apply(10)); // 輸出 "Num: 10"

3.2. 多參數(shù)變體

接口 方法簽名

BiFunction<T,U,R> R apply(T t, U u)

BiFunction<String, String, String> concat = (s1, s2) -> s1 + s2;
System.out.println(concat.apply("Hello", "World")); // 輸出 HelloWorld

4. 實際應(yīng)用

4.1. Stream API 中的 map 操作

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 將名字轉(zhuǎn)為大寫
List<String> upperNames = names.stream()
    .map(name -> name.toUpperCase()) // 這里使用Function
    .collect(Collectors.toList());

4.2. 策略模式實現(xiàn)

// 定義不同的處理策略
Map<String, Function<String, String>> processors = new HashMap<>();
processors.put("upper", String::toUpperCase);
processors.put("lower", String::toLowerCase);
processors.put("reverse", s -> new StringBuilder(s).reverse().toString());
// 使用策略
String input = "Hello";
String output = processors.get("upper").apply(input); // 輸出 "HELLO"

4.3. 方法鏈式處理

Function<Integer, Integer> times2 = x -> x * 2;
Function<Integer, Integer> minus1 = x -> x - 1;
// 組合函數(shù):先乘2再減1
Function<Integer, Integer> chain = times2.andThen(minus1);
System.out.println(chain.apply(10)); // 輸出 19

4.4. 性能考慮

對象創(chuàng)建開銷:每次使用 lambda 表達式都會創(chuàng)建一個新對象

自動裝箱問題:對于基本類型,使用特化接口(如 IntFunction)更高效

JIT 優(yōu)化:HotSpot 虛擬機會對 lambda 進行優(yōu)化

5. 高級使用

5.1. 柯里化(Currying)

5.1.1. 示例

// 將二元函數(shù)轉(zhuǎn)換為一元函數(shù)鏈
Function<Integer, Function<Integer, Integer>> adder = a -> b -> a + b;
Function<Integer, Integer> add5 = adder.apply(5);	
System.out.println(add5.apply(3)); // 輸出 8

5.1.2. 概念

柯里化的核心思想是:將一個接受多個參數(shù)的函數(shù),轉(zhuǎn)換成一系列使用一個參數(shù)的函數(shù)。

原始加法函數(shù)

BiFunction<Integer, Integer, Integer> normalAdd = (a, b) -> a + b;

柯里化后的加法函數(shù)

BiFunction<Integer, Integer, Integer> normalAdd = (a, b) -> a + b;

5.1.3. 示例解析

<code>Function<Integer, Function<Integer, Integer>> adder = a -> b -> a + b;
Function<Integer, Integer> add5 = adder.apply(5);
System.out.println(add5.apply(3)); // 輸出 8
------------------------------------------------------------------------
1.定義柯里化函數(shù):
Function<Integer, Function<Integer, Integer>> adder = a -> b -> a + b;
// 這是一個函數(shù),接受一個整數(shù)a,返回另一個函數(shù)
// 返回的函數(shù)接受整數(shù)b,返回a + b的結(jié)果
------------------------------------------------------------------------
2.部分應(yīng)用:
Function<Integer, Integer> add5 = adder.apply(5);
// 調(diào)用adder.apply(5)固定了第一個參數(shù)a=5
// 返回的新函數(shù)add5只需要一個參數(shù)b,計算5 + b
------------------------------------------------------------------------
3.完成計算:
add5.apply(3) // 返回8
// 向add5提供第二個參數(shù)3
// 執(zhí)行計算5 + 3 = 8
------------------------------------------------------------------------
</code>

5.1.4. 實際運用場景

5.1.4.1. 創(chuàng)建帶前綴的日志函數(shù)

// 創(chuàng)建帶前綴的日志函數(shù)
Function<String, Consumer<String>> logger = prefix -> message -> 
    System.out.println("[" + prefix + "] " + message);
Consumer<String> appLog = logger.apply("APP");
appLog.accept("Starting system..."); // 輸出: [APP] Starting system...

5.1.4.2. Web開發(fā)中的中間件:

// 模擬中間件鏈
Function<String, Function<HttpRequest, HttpResponse>> middleware = 
    authToken -> request -> {
        if(validToken(authToken)) {
            return process(request);
        }
        return new HttpResponse(403);
    };

5.2. 異常處理包裝

5.2.1. 示例

@FunctionalInterface
interface CheckedFunction<T, R> {
    R apply(T t) throws Exception;
}
public static <T, R> Function<T, R> wrap(CheckedFunction<T, R> checkedFunction) {
    return t -> {
        try {
            return checkedFunction.apply(t);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    };
}
// 使用
Function<String, Integer> safeParse = wrap(Integer::parseInt);

5.2.2. 問題背景

在Java中,函數(shù)式接口如Function不允許拋出受檢異常,但像Integer.parseInt()這樣的方法會拋出NumberFormatException(雖然是運行時異常,但其他方法如IO操作會拋出受檢異常)。

5.2.3. 示例解析

1.@FunctionalInterface確保它只有一個抽象方法
@FunctionalInterface
--------------------------------------------------------------------------------------
2.這是一個自定義的函數(shù)式接口
與標準Function接口的關(guān)鍵區(qū)別是允許apply()拋出Exception
interface CheckedFunction<T, R> {
    R apply(T t) throws Exception;
}
--------------------------------------------------------------------------------------
3.將CheckedFunction轉(zhuǎn)換為標準的Function
使用try-catch捕獲所有異常
將受檢異常包裝為RuntimeException
public static <T, R> Function<T, R> wrap(CheckedFunction<T, R> checkedFunction) {
    return t -> {  // 返回一個標準的Function
        try {
            return checkedFunction.apply(t);  // 執(zhí)行可能拋出異常的操作
        } catch (Exception e) {
            throw new RuntimeException(e);  // 包裝為運行時異常
        }
    };
}
--------------------------------------------------------------------------------------
4.Integer::parseInt方法引用作為CheckedFunction輸入
返回的safeParse是一個標準的Function,可以在Stream等場景直接使用
Function<String, Integer> safeParse = wrap(Integer::parseInt);

5.2.4. 深入理解

5.2.4.1. 為什么需要這樣包裝?

Java的函數(shù)式編程接口(如Function、Consumer等)的抽象方法不允許拋出受檢異常。這種包裝模式解決了:

允許在lambda表達式中使用會拋出異常的方法

保持與現(xiàn)有函數(shù)式接口的兼容性

5.2.4.2. 統(tǒng)一異常處理方式

定制異常處理:

public static <T, R> Function<T, R> wrap(
    CheckedFunction<T, R> checkedFunction, 
    Function<Exception, R> exceptionHandler) {
    return t -> {
        try {
            return checkedFunction.apply(t);
        } catch (Exception e) {
            return exceptionHandler.apply(e);
        }
    };
}
// 使用:解析失敗時返回null
Function<String, Integer> safeParse = wrap(
    Integer::parseInt, 
    e -> null
);

5.2.5. 實際應(yīng)用場景

5.2.5.1. Stream處理中的異常

List<String> numbers = Arrays.asList("1", "2", "abc", "4");
// 不使用包裝會很難處理異常
List<Integer> parsed = numbers.stream()
    .map(wrap(Integer::parseInt))  // 使用包裝方法
    .collect(Collectors.toList()); // 遇到錯誤會拋出RuntimeException

5.2.5.2. 文件操作

// 讀取文件所有行
Function<Path, List<String>> readLines = wrap(path -> 
    Files.readAllLines(path, StandardCharsets.UTF_8));
List<String> lines = readLines.apply(Paths.get("data.txt"));

5.2.5.3. 數(shù)據(jù)庫操作

// 查詢用戶
Function<Long, User> findUser = wrap(id -> 
    userRepository.findById(id).orElseThrow());
User user = findUser.apply(123L);

5.2.6. 完整工具類示例

public class FunctionWrappers {
    @FunctionalInterface
    public interface CheckedFunction<T, R> {
        R apply(T t) throws Exception;
    }
    // 基本包裝方法
    public static <T, R> Function<T, R> wrap(CheckedFunction<T, R> checkedFunction) {
        return t -> {
            try {
                return checkedFunction.apply(t);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        };
    }
    // 帶異常處理的包裝
    public static <T, R> Function<T, R> wrap(
        CheckedFunction<T, R> checkedFunction,
        Function<Exception, R> exceptionHandler) {
        return t -> {
            try {
                return checkedFunction.apply(t);
            } catch (Exception e) {
                return exceptionHandler.apply(e);
            }
        };
    }
    // 針對Consumer的包裝
    @FunctionalInterface
    public interface CheckedConsumer<T> {
        void accept(T t) throws Exception;
    }
    public static <T> Consumer<T> wrapConsumer(CheckedConsumer<T> checkedConsumer) {
        return t -> {
            try {
                checkedConsumer.accept(t);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        };
    }
}

6. Java Consumer 接口詳解

Consumer 是 Java 8 引入的一個核心函數(shù)式接口,屬于 java.util.function 包。它代表一個"接受單個輸入?yún)?shù)但不返回結(jié)果"的操作。

6.1. Consumer 的基本定義

T:輸入?yún)?shù)類型

核心方法:accept(T t) 執(zhí)行操作

特點:有輸入無輸出(與 Function 不同)

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);  // 核心抽象方法
    // 默認方法(組合操作)
    default Consumer<T> andThen(Consumer<? super T> after)
}

6.2. 核心方法解析

1. accept(T t)
執(zhí)行消費操作:
Consumer<String> printConsumer = s -> System.out.println(s);
printConsumer.accept("Hello");  // 輸出 "Hello"
----------------------------------------------------------------------------
2. andThen(Consumer after)
組合多個 Consumer(按順序執(zhí)行):
Consumer<String> printUpper = s -> System.out.println(s.toUpperCase());
Consumer<String> printLower = s -> System.out.println(s.toLowerCase());
Consumer<String> combined = printUpper.andThen(printLower);
combined.accept("Java"); 
// 輸出:
// JAVA
// java
----------------------------------------------------------------------------

6.3. Consumer 的變體

Java 還提供了 Consumer 的特化版本:

接口 方法簽名 說明

IntConsumer void accept(int) 處理 int 類型

LongConsumer void accept(long) 處理 long 類型

DoubleConsumer void accept(double) 處理 double 類型

BiConsumer<T,U> void accept(T t, U u) 處理兩個參數(shù)

6.4. 典型運用場景

6.4.1. 集合遍歷

List<String> names = List.of("Alice", "Bob", "Charlie");
// 傳統(tǒng)方式
for (String name : names) {
    System.out.println(name);
}
// 使用 Consumer
names.forEach(name -> System.out.println(name));
// 使用方法引用
names.forEach(System.out::println);

6.4.2. 資源處理

Consumer<Path> fileProcessor = path -> {
    try {
        String content = Files.readString(path);
        System.out.println(content);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
};
fileProcessor.accept(Paths.get("data.txt"));

6.4.3. 對象配置

class Person {
    String name;
    int age;
    // setters...
}
Consumer<Person> configurator = p -> {
    p.setName("Default");
    p.setAge(30);
};
Person person = new Person();
configurator.accept(person);

6.4.4. 日志記錄

BiConsumer<String, Object> logger = (level, msg) -> {
    System.out.printf("[%s] %s - %s%n", 
        LocalDateTime.now(), level, msg);
};
logger.accept("INFO", "Application started");

6.5. 相關(guān)接口對比

接口 方法簽名 特點

Consumer<T> void accept(T) 有輸入無輸出

Function<T,R> R apply(T) 有輸入有輸出

Supplier<T> T get() 無輸入有輸出

Predicate<T> boolean test(T) 有輸入,輸出布爾值

6.6. 高級用法

6.6.1. 異常處理包裝

@FunctionalInterface
interface CheckedConsumer<T> {
    void accept(T t) throws Exception;
}
public static <T> Consumer<T> wrap(CheckedConsumer<T> checkedConsumer) {
    return t -> {
        try {
            checkedConsumer.accept(t);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    };
}
// 使用
Consumer<Path> safeFileReader = wrap(path -> {
    String content = Files.readString(path);
    System.out.println(content);
});

6.6.2. 條件消費

public static <T> Consumer<T> conditional(
    Predicate<T> condition, 
    Consumer<T> consumer) {
    return t -> {
        if (condition.test(t)) {
            consumer.accept(t);
        }
    };
}
// 只打印長度大于3的字符串
Consumer<String> selectivePrint = conditional(
    s -> s.length() > 3, 
    System.out::println
);
selectivePrint.accept("Hi");    // 不輸出
selectivePrint.accept("Hello"); // 輸出 "Hello"

6.6.3. 構(gòu)建處理管道

Consumer<String> pipeline = ((Consumer<String>) s -> System.out.println("Original: " + s))
    .andThen(s -> System.out.println("Upper: " + s.toUpperCase()))
    .andThen(s -> System.out.println("Length: " + s.length()));
pipeline.accept("Java");
/* 輸出:
Original: Java
Upper: JAVA
Length: 4
*/

6.7. 注意事項

6.7.1. 命名規(guī)范

// 好的命名
Consumer<String> logMessage = msg -> System.out.println(msg);
// 不好的命名
Consumer<String> c = m -> System.out.println(m);

6.7.2. 保持簡潔

// 簡單邏輯直接用lambda
names.forEach(System.out::println);
// 復(fù)雜邏輯提取方法
names.forEach(this::processName);

6.7.3. 避免副作用

// 不推薦(修改外部狀態(tài))
List<String> result = new ArrayList<>();
names.forEach(name -> result.add(name.toUpperCase()));
// 推薦(使用stream)
List<String> result = names.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());

到此這篇關(guān)于Java 中的 Function 接口的文章就介紹到這了,更多相關(guān)Java Function 接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Maven工程引入依賴失敗Dependencies全部飄紅問題

    Maven工程引入依賴失敗Dependencies全部飄紅問題

    這篇文章主要介紹了Maven工程引入依賴失敗Dependencies全部飄紅問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • SpringBoot基礎(chǔ)框架詳解

    SpringBoot基礎(chǔ)框架詳解

    SpringBoot開發(fā)目的是為了簡化Spring應(yīng)用的創(chuàng)建、運行、調(diào)試和部署等,使用Spring Boot可以不用或者只需要很少的Spring配置就可以讓企業(yè)項目快速運行起來,本文介紹SpringBoot基礎(chǔ)框架詳解,感興趣的朋友一起看看吧
    2025-05-05
  • Java由淺入深講解繼承下

    Java由淺入深講解繼承下

    繼承就是可以直接使用前輩的屬性和方法。自然界如果沒有繼承,那一切都是處于混沌狀態(tài)。多態(tài)是同一個行為具有多個不同表現(xiàn)形式或形態(tài)的能力。多態(tài)就是同一個接口,使用不同的實例而執(zhí)行不同操作
    2022-04-04
  • MyBatis使用<foreach>標簽報錯問題及解決

    MyBatis使用<foreach>標簽報錯問題及解決

    這篇文章主要介紹了MyBatis使用<foreach>標簽報錯問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Java中LocalDateTime的具體用法

    Java中LocalDateTime的具體用法

    本文主要介紹了Java中LocalDateTime的具體用法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • Pulsar源碼徹底解決重復(fù)消費問題

    Pulsar源碼徹底解決重復(fù)消費問題

    這篇文章主要為大家介紹了Pulsar源碼徹底解決重復(fù)消費問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • 前端如何調(diào)用后端接口進行數(shù)據(jù)交互詳解(axios和SpringBoot)

    前端如何調(diào)用后端接口進行數(shù)據(jù)交互詳解(axios和SpringBoot)

    一般來講前端不會給后端接口,而是后端給前端接口的情況比較普遍,下面這篇文章主要給大家介紹了關(guān)于前端如何調(diào)用后端接口進行數(shù)據(jù)交互的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • springboot如何使用sm2加密傳輸

    springboot如何使用sm2加密傳輸

    這篇文章主要介紹了springboot如何使用sm2加密傳輸問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Spring注解配置IOC,DI的方法詳解

    Spring注解配置IOC,DI的方法詳解

    這篇文章主要為大家介紹了vue組件通信的幾種方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • Java獲取IP地址以及MAC地址的示例代碼

    Java獲取IP地址以及MAC地址的示例代碼

    IP地址是用于在網(wǎng)絡(luò)上識別設(shè)備的唯一地址,而MAC地址是設(shè)備的物理地址,本文主要介紹了Java獲取IP地址以及MAC地址的示例代碼,具有一定的參考價值,感興趣的可以了解一下
    2024-04-04

最新評論

红河县| 松江区| 承德市| 资溪县| 泊头市| 莱阳市| 托克逊县| 蒙自县| 英超| 凤山县| 江达县| 淄博市| 会理县| 阿克陶县| 江门市| 富宁县| 天峻县| 茶陵县| 肃南| 宝坻区| 柳河县| 启东市| 根河市| 曲阳县| 贵德县| 彭阳县| 会东县| 东明县| 盱眙县| 天峻县| 大竹县| 莱阳市| 安达市| 甘孜县| 达孜县| 丁青县| 灵宝市| 长阳| 道孚县| 上饶市| 甘孜|