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

Java8利用Function接口減少代碼重復的操作指南

 更新時間:2025年07月28日 10:06:54   作者:IT楓斗者  
在Java開發(fā)的征途中,我們時常與重復代碼不期而遇,這些重復代碼不僅讓項目顯得笨重,更增加了維護成本,本文將以一個實際應用場景為例,即使用Java 8的函數(shù)式編程特性來重構數(shù)據(jù)有效性斷言邏輯,展示如何通過SFunction減少代碼重復,需要的朋友可以參考下

前言

Java 開發(fā)的征途中,我們時常與重復代碼不期而遇。這些重復代碼不僅讓項目顯得笨重,更增加了維護成本。幸運的是,Java 8 帶來了函數(shù)式編程的春風,以 Function 接口為代表的一系列新特性,為我們提供了破除這一難題的利劍。本文將以一個實際應用場景為例,即使用 Java 8 的函數(shù)式編程特性來重構數(shù)據(jù)有效性斷言邏輯,展示如何通過 SFunction(基于 Java 8Lambda 表達式封裝)減少代碼重復,從而提升代碼的優(yōu)雅性和可維護性。

背景故事:數(shù)據(jù)校驗的煩惱

想象一下,在一個復雜的業(yè)務系統(tǒng)中,我們可能需要頻繁地驗證數(shù)據(jù)庫中某個字段值是否有效,是否符合預期值。傳統(tǒng)的做法可能充斥著大量相似的查詢邏輯,每次都需要手動構建查詢條件、執(zhí)行查詢并處理結果,這樣的代碼既冗長又難以維護。

例如以下兩個驗證用戶 ID 和部門 ID 是否有效的方法,雖然簡單,但每次需要校驗不同實體或不同條件時,就需要復制粘貼并做相應修改,導致代碼庫中充滿了大量雷同的校驗邏輯,給維護帶來了困擾。

java 體驗AI代碼助手 代碼解讀復制代碼// 判斷用戶 ID 是否有效
public void checkUserExistence(String userId) {
    User user = userDao.findById(userId);
    if (user == null) {
        throw new RuntimeException("用戶ID無效");
    }
}

// 判斷部門 ID 是否有效
public void checkDeptExistence(String deptId) {
    Dept dept = deptDao.findById(deptId);
    if (dept == null) {
        throw new RuntimeException("部門ID無效");
    }   
}

Java 8 的魔法棒:函數(shù)式接口

Java 8 引入了函數(shù)式接口的概念,其中 Function<T, R> 是最基礎的代表,它接受一個類型 T 的輸入,返回類型 R 的結果。而在 MyBatis Plus 等框架中常用的 SFunction 是對 Lambda 表達式的進一步封裝,使得我們可以更加靈活地操作實體類的屬性。

實戰(zhàn)演練:重構斷言方法

下面的 ensureColumnValueValid 方法正是利用了函數(shù)式接口的魅力,實現(xiàn)了對任意實體類指定列值的有效性斷言:

java 體驗AI代碼助手 代碼解讀復制代碼/**
 * 確認數(shù)據(jù)庫字段值有效(通用)
 * 
 * @param <V> 待驗證值的類型
 * @param valueToCheck 待驗證的值
 * @param columnExtractor 實體類屬性提取函數(shù)
 * @param queryExecutor 單條數(shù)據(jù)查詢執(zhí)行器
 * @param errorMessage 異常提示信息模板
 */
public static <T, R, V> void ensureColumnValueValid(V valueToCheck, SFunction<T, R> columnExtractor, SFunction<LambdaQueryWrapper<T>, T> queryExecutor, String errorMessage) {
    if (valueToCheck == null) return;
    
    LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
    wrapper.select(columnExtractor);
    wrapper.eq(columnExtractor, valueToCheck);
    wrapper.last("LIMIT 1");

    T entity = queryExecutor.apply(wrapper);
    R columnValue = columnExtractor.apply(entity);
    if (entity == null || columnValue == null)
        throw new DataValidationException(String.format(errorMessage, valueToCheck));
}

這個方法接受一個待驗證的值、一個實體類屬性提取函數(shù)、一個單行數(shù)據(jù)查詢執(zhí)行器和一個異常信息模板作為參數(shù)。通過這四個參數(shù),不僅能夠進行針對特定屬性的有效性檢查,而且還能生成具有一致性的異常信息。

對比分析

使用 Function 改造前

java 體驗AI代碼助手 代碼解讀復制代碼// 判斷用戶 ID 是否有效
public void checkUserExistence(String userId) {
    User user = userDao.findById(userId);
    if (user == null) {
        throw new RuntimeException("用戶ID無效");
    }
}

// 判斷部門 ID 是否有效
public void checkDeptExistence(String deptId) {
    Dept dept = deptDao.findById(deptId);
    if (dept == null) {
        throw new RuntimeException("部門ID無效");
    }   
}

使用 Function 改造后

java 體驗AI代碼助手 代碼解讀復制代碼public void assignTaskToUser(AddOrderDTO dto) {
    ensureColumnValueValid(dto.getUserId(), User::getId, userDao::getOne, "用戶ID無效");
    ensureColumnValueValid(dto.getDeptId(), Dept::getId, deptDao::getOne, "部門ID無效");    
    ensureColumnValueValid(dto.getCustomerId(), Customer::getId, customerDao::getOne, "客戶ID無效");
    ensureColumnValueValid(dto.getDeptId(), Dept::getId, deptDao::getOne, "部門ID無效");
    ensureColumnValueValid(dto.getSupplieId(), Supplie::getId, supplierDao::getOne, "供應商ID無效");

    // 現(xiàn)在可以確信客戶存在
    Customer cus = customerDao.findById(dto.getCustomerId());     
    
    // 創(chuàng)建訂單的邏輯...
}

對比上述兩段代碼,我們發(fā)現(xiàn)后者不僅大幅減少了代碼量,而且通過函數(shù)式編程,表達出更為清晰的邏輯意圖,可讀性和可維護性都有所提高。

優(yōu)點

  1. 減少重復代碼: 通過 ensureColumnValueValid 方法,所有涉及數(shù)據(jù)庫字段值有效性檢查的地方都可以復用相同的邏輯,將變化的部分作為參數(shù)傳遞,大大減少了因特定校驗邏輯而產(chǎn)生的代碼量。
  2. 增強代碼復用: 抽象化的校驗方法適用于多種場景,無論是用戶ID、訂單號還是其他任何實體屬性的校驗,一套邏輯即可應對。
  3. 提升可讀性和維護性: 通過清晰的函數(shù)簽名和 Lambda 表達式,代碼意圖一目了然,降低了后續(xù)維護的成本。
  4. 靈活性和擴展性: 當校驗規(guī)則發(fā)生變化時,只需要調(diào)整 ensureColumnValueValid 方法或其內(nèi)部實現(xiàn),所有調(diào)用該方法的地方都會自動受益,提高了系統(tǒng)的靈活性和擴展性。

舉一反三:拓展校驗邏輯的邊界

通過上述的實踐,我們見識到了函數(shù)式編程在簡化數(shù)據(jù)校驗邏輯方面的威力。但這只是冰山一角,我們可以根據(jù)不同的業(yè)務場景,繼續(xù)擴展和完善校驗邏輯,實現(xiàn)更多樣化的校驗需求。以下兩個示例展示了如何在原有基礎上進一步深化,實現(xiàn)更復雜的數(shù)據(jù)比較和驗證功能。

斷言指定列值等于預期值

首先,考慮一個場景:除了驗證數(shù)據(jù)的存在性,我們還需確認查詢到的某列值是否與預期值相符。這在驗證用戶角色、狀態(tài)變更等場景中尤為常見。為此,我們設計了 validateColumnValueMatchesExpected 方法:

java 體驗AI代碼助手 代碼解讀復制代碼/**
 * 驗證查詢結果中指定列的值是否與預期值匹配
 *
 * @param <T>             實體類型
 * @param <R>             目標列值的類型
 * @param <C>             查詢條件列值的類型
 * @param targetColumn    目標列的提取函數(shù),用于獲取想要驗證的列值
 * @param expectedValue   期望的列值
 * @param conditionColumn 條件列的提取函數(shù),用于設置查詢條件
 * @param conditionValue  條件列對應的值
 * @param queryMethod     執(zhí)行查詢的方法引用,返回單個實體對象
 * @param errorMessage    驗證失敗時拋出異常的錯誤信息模板
 * @throws RuntimeException 當查詢結果中目標列的值與預期值不匹配時拋出異常
 */
public static <T, R, C> void validateColumnValueMatchesExpected(
      SFunction<T, R> targetColumn, R expectedValue,
      SFunction<T, C> conditionColumn, C conditionValue,
      SFunction<LambdaQueryWrapper<T>, T> queryMethod,
      String errorMessage) {

   // 創(chuàng)建查詢包裝器,選擇目標列并設置查詢條件
   LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
   wrapper.select(targetColumn);
   wrapper.eq(conditionColumn, conditionValue);

   // 執(zhí)行查詢方法
   T one = queryMethod.apply(wrapper);
   // 如果查詢結果為空,則直接返回,視為驗證通過(或忽略)
   if (one == null) return;

   // 獲取查詢結果中目標列的實際值
   R actualValue = targetColumn.apply(one);

   // 比較實際值與預期值是否匹配,這里假設notMatch是一個自定義方法用于比較不匹配情況
   boolean doesNotMatch = notMatch(actualValue, expectedValue);
   if (doesNotMatch) {
      // 若不匹配,則根據(jù)錯誤信息模板拋出異常
      throw new RuntimeException(String.format(errorMessage, expectedValue, actualValue));
   }
}

// 假設的輔助方法,用于比較值是否不匹配,根據(jù)實際需要實現(xiàn)
private static <R> boolean notMatch(R actual, R expected) {
    // 示例簡單實現(xiàn)為不相等判斷,實際情況可能更復雜
    return !Objects.equals(actual, expected);
}

這個方法允許我們指定一個查詢目標列(targetColumn)、預期值(expectedValue)、查詢條件列(conditionColumn)及其對應的條件值(conditionValue),并提供一個查詢方法(queryMethod)來執(zhí)行查詢。如果查詢到的列值與預期不符,則拋出異常,錯誤信息通過 errorMessage 參數(shù)定制。

應用場景: 例如在一個權限管理系統(tǒng)中,當需要更新用戶角色時,系統(tǒng)需要確保當前用戶的角色在更新前是 “普通用戶”,才能將其升級為 “管理員”。此場景下,可以使用 validateColumnValueMatchesExpected 方法來驗證用戶當前的角色是否確實為“普通用戶”。

java 體驗AI代碼助手 代碼解讀復制代碼// 當用戶角色不是 “普通用戶” 時拋異常
validateColumnValueMatchesExpected(User::getRoleType, "普通用戶", User::getId, userId, userMapper::getOne, "用戶角色不是普通用戶,無法升級為管理員!");

斷言指定值位于期望值列表內(nèi)

進一步,某些情況下我們需要驗證查詢結果中的某一列值是否屬于一個預設的值集合。例如,驗證用戶角色是否合法。為此,我們創(chuàng)建了 validateColumnValueMatchesExpectedList 方法:

java 體驗AI代碼助手 代碼解讀復制代碼/**
 * 驗證查詢結果中指定列的值是否位于預期值列表內(nèi)
 *
 * @param <T>             實體類型
 * @param <R>             目標列值的類型
 * @param <C>             查詢條件列值的類型
 * @param targetColumn    目標列的提取函數(shù),用于獲取想要驗證的列值
 * @param expectedValueList 期望值的列表
 * @param conditionColumn 條件列的提取函數(shù),用于設置查詢條件
 * @param conditionValue  條件列對應的值
 * @param queryMethod     執(zhí)行查詢的方法引用,返回單個實體對象
 * @param errorMessage    驗證失敗時拋出異常的錯誤信息模板
 * @throws RuntimeException 當查詢結果中目標列的值不在預期值列表內(nèi)時拋出異常
 */
public static <T, R, C> void validateColumnValueInExpectedList(
        SFunction<T, R> targetColumn, List<R> expectedValueList,
        SFunction<T, C> conditionColumn, C conditionValue,
        SFunction<LambdaQueryWrapper<T>, T> queryMethod,
        String errorMessage) {

    LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
    wrapper.select(targetColumn);
    wrapper.eq(conditionColumn, conditionValue);

    T one = queryMethod.apply(wrapper);
    if (one == null) return;

    R actualValue = targetColumn.apply(one);
    if (actualValue == null) throw new RuntimeException("列查詢結果為空");

    if (!expectedValueList.contains(actualValue)) {        
        throw new RuntimeException(errorMessage);
    }
}

這個方法接受一個目標列(targetColumn)、一個預期值列表(expectedValueList)、查詢條件列(conditionColumn)及其條件值(conditionValue),同樣需要一個查詢方法(queryMethod)。如果查詢到的列值不在預期值列表中,則觸發(fā)異常。

應用場景: 在一個電商平臺的訂單處理流程中,系統(tǒng)需要驗證訂單狀態(tài)是否處于可取消的狀態(tài)列表里(如 “待支付”、“待發(fā)貨”)才允許用戶取消訂單。此時,validateColumnValueInExpectedList 方法能有效確保操作的合法性。

// 假設 OrderStatusEnum 枚舉了所有可能的訂單狀態(tài),cancelableStatuses 包含可取消的狀態(tài)
List<String> cancelableStatuses = Arrays.asList(OrderStatusEnum.WAITING_PAYMENT.getValue(), OrderStatusEnum.WAITING_DELIVERY.getValue());

// 驗證訂單狀態(tài)是否在可取消狀態(tài)列表內(nèi)
validateColumnValueInExpectedList(Order::getStatus, cancelableStatuses, Order::getOrderId, orderId, orderMapper::selectOne, "訂單當前狀態(tài)不允許取消!");

通過這兩個擴展方法,我們不僅鞏固了函數(shù)式編程在減少代碼重復、提升代碼靈活性方面的優(yōu)勢,還進一步證明了通過抽象和泛型設計,可以輕松應對各種復雜的業(yè)務校驗需求,使代碼更加貼近業(yè)務邏輯,易于理解和維護。

核心優(yōu)勢

  1. 代碼復用:通過泛型和函數(shù)式接口,該方法能夠適應任何實體類和屬性的校驗需求,大大減少了重復的查詢邏輯代碼。
  2. 清晰表達意圖:方法簽名直觀表達了校驗邏輯的目的,提高了代碼的可讀性和可維護性。
  3. 靈活性:使用者只需提供幾個簡單的 Lambda 表達式,即可完成復雜的查詢邏輯配置,無需關心底層實現(xiàn)細節(jié)。
  4. 易于維護與擴展:
    1. 當需要增加新的實體驗證時,僅需調(diào)用 ensureColumnValueValid 并傳入相應的參數(shù),無需編寫新的驗證邏輯,降低了維護成本。
    2. 修改驗證規(guī)則時,只需調(diào)整 ensureColumnValueValid 內(nèi)部實現(xiàn),所有調(diào)用處自動遵循新規(guī)則,便于統(tǒng)一管理。
    3. 異常處理集中于 ensureColumnValueValid 方法內(nèi)部,統(tǒng)一了異常拋出行為,避免了在多個地方處理相同的邏輯錯誤,減少了潛在的錯誤源。

以上就是Java8利用Function接口減少代碼重復的操作指南的詳細內(nèi)容,更多關于Java8 Function減少代碼重復的資料請關注腳本之家其它相關文章!

相關文章

  • 通過實例解析傳統(tǒng)jar包引用方式

    通過實例解析傳統(tǒng)jar包引用方式

    這篇文章主要介紹了通過實例解析傳統(tǒng)jar包引用方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • javax.servlet不存在的解決辦法

    javax.servlet不存在的解決辦法

    今天在關于servlet的編譯中出現(xiàn)了一下小小的錯誤,發(fā)現(xiàn)javax.servlet不存在,本文就介紹一下解決方法,感興趣的可以了解一下
    2021-07-07
  • SpringCloud分布式項目下feign的使用示例詳解

    SpringCloud分布式項目下feign的使用示例詳解

    這篇文章主要介紹了SpringCloud分布式項目下feign的使用,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • MyBatis學習教程(五)-實現(xiàn)關聯(lián)表查詢方法詳解

    MyBatis學習教程(五)-實現(xiàn)關聯(lián)表查詢方法詳解

    本文給大家介紹mybatis關聯(lián)查詢,包括一對一關聯(lián)查詢,一對多關聯(lián)查詢,代碼簡單易懂,感興趣的朋友一起學習吧
    2016-05-05
  • Java之實現(xiàn)十進制與十六進制轉換案例講解

    Java之實現(xiàn)十進制與十六進制轉換案例講解

    這篇文章主要介紹了Java之實現(xiàn)十進制與十六進制轉換案例講解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • SpringMvc中的Bean加載機制詳解

    SpringMvc中的Bean加載機制詳解

    這篇文章主要介紹了SpringMvc中的Bean加載機制詳解,在Spring MVC中,Bean的作用主要是處理應用程序的業(yè)務邏輯和數(shù)據(jù),例如,一個用戶管理應用程序的Bean可能包括UserService、UserDao和UserController等,需要的朋友可以參考下
    2023-12-12
  • java操作mongodb時,對象bean和DBObject相互轉換的方法(推薦)

    java操作mongodb時,對象bean和DBObject相互轉換的方法(推薦)

    下面小編就為大家?guī)硪黄猨ava操作mongodb時,對象bean和DBObject相互轉換的方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • Java如何使用JSR303校驗數(shù)據(jù)與自定義校驗注解

    Java如何使用JSR303校驗數(shù)據(jù)與自定義校驗注解

    這篇文章主要介紹了Java如何使用JSR303校驗數(shù)據(jù)與自定義校驗注解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • 詳解JAVA 線程-線程的狀態(tài)有哪些?它是如何工作的?

    詳解JAVA 線程-線程的狀態(tài)有哪些?它是如何工作的?

    這篇文章主要介紹了詳解JAVA 線程的的相關資料,文中講解非常細致,源碼幫助大家更好的理解和學習,感興趣的朋友可以參考下
    2020-06-06
  • springboot2.3之后hibernate-validator依賴缺失【踩坑】

    springboot2.3之后hibernate-validator依賴缺失【踩坑】

    這篇文章主要介紹了springboot2.3之后hibernate-validator依賴缺失【踩坑】,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11

最新評論

多伦县| 贵州省| 苍南县| 郁南县| 福鼎市| 永寿县| 定远县| 兴文县| 扎赉特旗| 景洪市| 郧西县| 荃湾区| 聊城市| 南溪县| 会东县| 湾仔区| 宣化县| 福清市| 仁化县| 靖边县| 临洮县| 白山市| 凌源市| 海门市| 盖州市| 翁牛特旗| 金塔县| 通渭县| 安福县| 长葛市| 开化县| 凤阳县| 昭觉县| 监利县| 彰化市| 青神县| 海阳市| 顺平县| 新密市| 扎兰屯市| 上思县|