1. 程式人生 > >Java8新特性-Lambda-實戰(一)

Java8新特性-Lambda-實戰(一)

起因

今天早上和小夥伴閒聊中講到了程式碼中很多switch case,或者if else if…感覺low到爆,然後大神用反射方法對這邊進行了改造,程式碼瞬間看上去好多了。
下午review自己專案中的程式碼,竟然也發現了這類程式碼,需求是根據關鍵字判斷關鍵字的型別,手機?QQ?EMAIL…,之前看了Java8實戰,就有了一些想法,也對為什麼要出現函式式變成,函式式介面有了一些理解,有點茅塞頓開的感覺

原始程式碼

首先是一個用來驗證的類MatchUtil

public class MatchUtil {

/**
 * 校驗是否為電話號碼
 */
public static boolean isPhone(String val) {
    if (val == null || val.length() < 7) {// 至少7個字元
        return false;
    }
    Pattern pattern = Pattern
            .compile("("
                    + "^(\\+?86|\\(\\+?86\\)){0,1}\\d{11}$"
                    + "|^(\\d{3,4}|\\(\\d{3,4}\\))(-| ){0,1}(\\d{7,8})$"
                    + "|^(\\d{3,4}|\\(\\d{3,4}\\))(-| ){0,1}(\\d{7,8})(-| )(\\d{1,4})$"
                    + "|^(\\d{7,8})((-| )\\d{1,4}){0,1}$" + ")");
    return pattern.matcher(val).matches();
}


/**
 * 校驗是否為QQ號碼
 */
public static boolean isQQ(String val) {
    if (val == null || val.length() < 5 || val.length() > 13) {// 5-13個字元
        return false;
    }
    // 5-13位數字
    Pattern pattern = Pattern.compile("^[1-9][0-9]{4,12}$");
    return pattern.matcher(val).matches();
}

/**
 * 校驗是否為Imsi號碼
 */
public static boolean isImsi(String val)
{
    Pattern pattern = Pattern.compile("^460[0-9]\\d{11}$");
    return pattern.matcher(val).matches();
}

/**
 * 校驗是否為合法身份證,只支援大陸身份證
 */
public static boolean isValidIDCard(String certid) {
    if (certid == null) {
        return false;
    }

    if (certid.length() == 18) {
        //此處省略方法
        return false;
    } else if (certid.length() == 15) {
        //此處省略方法
        return false;
    } else {
        return false;
    }
}

}

業務程式碼

由於篇幅原因,這裡只列舉了一部分else if 實際程式碼可能有10個左右吧

public class FunctionInterfacePractiseOri {

public static void main(String[] args) {

    String value = "13912911111";
    List<String> resourceTypeList = Arrays.asList("phone","qq","email","idcard","imsi");
    resourceTypeList.stream().filter(resourceType->matchResourceType(resourceType,value))
                             .findFirst().ifPresent(System.out::println);

}

/**
 * 判斷關鍵詞是否符合首頁固定型別的正則
 * @param resourceType
 * @param keyword
 * @return
 */
private static boolean matchResourceType(String resourceType, String keyword){
    boolean match = true ;

    if("phone".equals(resourceType)){
        match = MatchUtil.isPhone(keyword);
    }
    else if("qq".equals(resourceType)){
        match = MatchUtil.isQQ(keyword);
    }
    else if("imsi".equals(resourceType)){
        match = MatchUtil.isImsi(keyword);
    }
    else if("idcard".equals(resourceType)){
        match = MatchUtil.isValidIDCard(keyword);
    }
    return match ;
}

}

改造開始

一開始我的思路是將型別,和正則表示式做對映,然後程式碼利用keyword.match(reg),這樣就可以消除程式碼中的if else了。這條路看似不錯,但是到了驗證手機號碼的時候,問題來了,手機號的驗證不是簡單的一個正則就完事了,而是通過一個方法,裡面可能有複雜的業務邏輯。哎,要是可以將型別和方法做個對映關係就好了。

Wait!!!這不是需要一個函式式介面麼

Lambda來發揮威力了

配合Java8提供的Lambda表示式,結合java.util.function包下面的方法,我們就可以實現方法的繫結,輸入一個物件,返回boolean型別的邏輯可以使用的Predicate

public class FunctionInterfacePractise2 {

private static Map<String,Predicate<String>> typeRegMap = new HashMap<>();

static {
    //傳入Lambda表示式,這裡就可以傳入方法了
    typeRegMap.put("phone", (keyword)->MatchUtil.isPhone(keyword));
    //優化成函式引用寫法
    typeRegMap.put("qq",MatchUtil::isQQ);
    typeRegMap.put("idcard",MatchUtil::isValidIDCard);
}

public static void main(String[] args) {

    String value = "13912911111";
    List<String> resourceTypeList = Arrays.asList("phone","qq","email","idcard","imsi");
    resourceTypeList.stream().filter(resourceType->matchResourceTypeByFunction(resourceType,value))
                             .findFirst().ifPresent(System.out::println);
}

private static boolean matchResourceTypeByFunction(String resourceType, String keyword){
    Predicate<String> predicate =typeRegMap.get(resourceType);
    return predicate.test(keyword);
}

}

總結

java8的函式式的程式設計思想,讓傳遞方法變為了可能,會讓我們的程式碼更簡潔更易讀