国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

企業級lambda表達式,讓你對lambda有更好的理解

justCoding / 2564人閱讀

摘要:但,如果加入了函數式編程,也就是將方法作為形參傳遞,這必然讓開發者為難。但是,其他語言早就使用了函數式編程,比如最常見腳本語言。這就是函數式編程,傳遞的是一個函數直到,才引用了函數式編程,也就是我們所說的表達式。

導讀

Java從jdk1發展到今天,方法的形參類型可以是基本變量,可以是jdk自帶的類型,也可以是用戶自定義的類型,但是,方法能不能作為形參來傳遞?我們希望java能夠像其他編程語言,可以采用函數式編程思想,換句話說,是將方法當做對象來看,但其在jdk1.8之前都沒有這樣做。

Java為什么在jdk1.8之前沒有這樣做?正如我們所知道的,Java自面世以來,便以對象的方式立足。什么都是對象, 對象以方法傳遞消息,以屬性存儲數據。其又封裝了太多的底層操作,比如說像C++的指針。因而,學習Java的人,感覺到Java簡單,這也和Java的初衷相似。

但,如果加入了函數式編程,也就是將方法作為形參傳遞,這必然讓Java開發者為難。但是,其他語言早就使用了函數式編程,比如最常見JavaScript腳本語言。其就可以使用函數式編程,如下代碼所示:

    var intArr = [1, 2, 3, 4, 5];
    //這就是函數式編程,傳遞的是一個函數
    var newArr = intArr.map(function (item) {
        return item * item;
    })
    alert(newArr);

又因為return item * item;只是一條語句,就像是if當中的單語句可以省略大括號,這里也可以省略大括號,如下代碼;

  var newArr = intArr.map(item=> item * item)

但是,如果函數包含多條語句,我們不能這樣省略,還是上面的代碼。但是,條件變了,如果是偶數的話,同時,結果大于10,我們才輸出來。

var intArr = [1, 2, 3, 4, 5];
//這就是函數式編程,傳遞的是一個函數
var newArr = intArr.map(function (item) {
    var res=0;
    if (item % 2 == 0) {
        res = item * item;
        if (res >= 10) {
            return res;
        }
    }
})
alert(newArr);

直到jdk8,Java才引用了函數式編程,也就是我們所說的lambda表達式。其所對應希臘字母的λ,讀音為拉姆達。λ在數學中即表示參數,比如λ矩陣表達式。它也可以是一個表達式,也可以表示一個函數。因而,用它來命名是最為合適的。因為,函數式編程可以講方法作為形參使用。

Comparator接口

在講解lambda表達式前,我們先說說Comparator接口,這個想必學Java的都不陌生。它是jdk1.2之后引用的,不過,在jdk1.8的時候,上面加了個注解,如代碼所示:

@FunctionalInterface
public interface Comparator {
 。。。
}

這個注解是什么意思?我們拆開來看,Functional Interface函數式接口,只包含一個方法的接口。函數式接口有什么用?我們在后文再說。

我們經常以方法內部類,來使用該接口,做容器對象的排序所用。

比如,我們現在有一個項目人員類,如代碼所示:

/**
 * Created By zby on 22:39 2019/3/20
 */
@AllArgsConstructor
@Data
@NoArgsConstructor
@EqualsAndHashCode
@ToString
public class ProjectPerson {

    /**
     * 年齡
     */
    private int age;

    /**
     * 姓名
     */
    private String name;

    /**
     * 排序
     */
    private int sort;
    
}

我們使用hibernate框架獲取人員對象的集合后,像根據人員的年齡進行排序,如代碼所示:

public static void main(String[] args) {
    ProjectPerson person1 = new ProjectPerson(23, "zhubaoya1", 0);
    ProjectPerson person2 = new ProjectPerson(33, "zhubaoya2", 1);
    ProjectPerson person3 = new ProjectPerson(18, "zhubaoya3", 2);
    ProjectPerson person4 = new ProjectPerson(17, "zhubaoya4", 3);
    ProjectPerson person5 = new ProjectPerson(43, "zhubaoya5", 4);
    ProjectPerson person6 = new ProjectPerson(35, "zhubaoya6", 5);

    ProjectPerson[] people = new ProjectPerson[6];
    people[0] = person1;
    people[1] = person2;
    people[2] = person3;
    people[3] = person4;
    people[4] = person5;
    people[5] = person6;
    
    Arrays.sort(people, new Comparator() {
        @Override
        public int compare(ProjectPerson o1, ProjectPerson o2) {
            return o2.getAge() - o1.getAge();
        }
    });
    for (ProjectPerson person : people) {
        System.out.println(person);
    }
}

按倒序輸出結果為:
ProjectPerson{age=43, name="zhubaoya5", sort=4}
ProjectPerson{age=35, name="zhubaoya6", sort=5}
ProjectPerson{age=33, name="zhubaoya2", sort=1}
ProjectPerson{age=23, name="zhubaoya1", sort=0}
ProjectPerson{age=18, name="zhubaoya3", sort=2}
ProjectPerson{age=17, name="zhubaoya4", sort=3}

我們上文也說了,既然其是函數式編程,我們能不能將其像JavaScript那樣輸出數據呢?當然是可以的,因為,我們在編寫的時候,idea就有提示,可以用lambda表達式替代,如圖所示:

于是,我們用lambda表達式替代,如代碼所示:

 public static void main(String[] args) {
    。。。。。

    Arrays.sort(people,Comparator.comparing(ProjectPerson::getAge,(age1,age2)->Integer.compare(age2,age1)));
    
    for (ProjectPerson person : people) {
        System.out.println(person);
    }
}

對于上面的表達式,我們還可以這樣寫。但不推薦這樣寫,因為 Integer.compare(age2,age1);是單語句,可以省略大括號,就像上面那樣書寫。

Arrays.sort(people,Comparator.comparing(ProjectPerson::getAge,(age1,age2)->{
    return Integer.compare(age2,age1);
}));

其輸出的結果和上面的一樣,不過,這里使用了lambda表達式,那么,什么是lambda表達式呢?

lambda表達式

通過上面的表達式可以看出,lambda表達式傳遞的是函數體。我們來看Comparator.comparing這個方法,其內部什么樣的呢?

 public static  Comparator comparing(
        Function keyExtractor,
        Comparator keyComparator)
{
    Objects.requireNonNull(keyExtractor);
    Objects.requireNonNull(keyComparator);
    return (Comparator & Serializable)
        (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                          keyExtractor.apply(c2));
}

其有兩個參數,一個是函數對象,一個比較器對象。而比較器對象是有 @FunctionalInterface注解,這是jdk1.8才有的。也就是說,不是所有的方法,都可以改成lambda表達式。

如果方法的形參類有@FunctionalInterface接口,我們一般可以向其傳遞代碼塊。這是個很神奇的地方,方法中也可以寫入方法。正如,我們可以向其傳遞代碼塊,正如Comparator.comparing(ProjectPerson::getAge,(age1,age2)->Integer.compare(age2,age1))也就是方法。

lambda表達式一般這樣表示 形參 + 箭頭-> +方法體 這三部分,即

一個代碼塊

參數

自由變量的值。這是非參數而且不在代碼中定義的變量。

單個對象的Lambda

既然清楚了lambda表達式是怎么表示的,那么,我接下來就舉公司的例子:如果某個對象的屬性值不為空,我們就對該對象的屬性值操作,如以下代碼所示:

項目的實體類

/**
 * Created By zby on 21:21 2019/3/21
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Project {

    /**
     * 項目名
     */
    private String name;

    /**
     * 項目開始時間
     */
    private Date startTime;

    /**
     * 項目結束時間
     */
    private Date endTime;
}

lambdaUtil類

/**
 * Created By zby on 21:22 2019/3/21
 * 
 * @param value 參數值
 * @param function 可以接受任何一個參數,并返回響應的值。
 */
public static  void ifNotNullThen(T value, Consumer function) {
    if (value != null) {
        function.accept(value);
    }
}

Consumer也有@FunctionalInterface,其也有lambda表達式,如下代碼:

 public static void main(String[] args) {
    try {
        //            使用阿里巴巴的fastjson框架
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("validateTime", "");
        
         //            使用org.apache.commons的框架
        final FastDateFormat ISO_DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd");
        String startTime = "2018-12-22";
        Project project = new Project("新華城", ISO_DATE_FORMAT.parse(startTime), new Date());
        jsonObject.put("name", project.getName());
        
        // 使用lambda表達式,輸出項目名稱和項目有效期           
        LambdaUtil.ifNotNullThen(project.getEndTime(), t -> jsonObject.replace("validateTime", startTime + " - " + ISO_DATE_FORMAT.format(t)));
        System.out.println(jsonObject);
    } catch (ParseException e) {
        e.printStackTrace();
    }
}

輸出結果:
{"validateTime":"2018-12-22 - 2019-03-21","name":"新華城"}

其實,也可以不用lambda表達式,這樣寫也是可以的:

Date endTime=project.getEndTime();
if (endTime != null){
    jsonObject.replace("validateTime", startTime + " - "
            + ISO_DATE_FORMAT.format(endTime));
}

為什么用了lambda表達式呢,因為,lambda表達式可以簡化代碼,讓代碼變得不那么冗余。尤其是在遍歷集合時,更能顯示它的優點。

集合的lambda

lambdaUtil的方法

 /**
 * Created By zby on 22:21 2019/3/21
 * 過濾集合
 *
 * @param collection 使用容器的接口,保證了松散耦合
 * @param function   lambda表達式的代碼塊,map一個代碼塊,以集合的方式返回
 */
public static  List simpleMap(Collection collection, Function function) {
    if (collection != null && collection.size() > 0) {
        return collection.stream().map(function).collect(Collectors.toList());
    }
    return null;
}

使用上面的過濾方法

 public static void main(String[] args) {
    try {
        final FastDateFormat ISO_DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd");
        String startTime1 = "2018-12-22", endTime1 = "2019-03-12";
        String startTime2 = "2018-12-22", endTime2 = "2019-03-14";
        String startTime3 = "2018-12-22", endTime3 = "2019-03-16";
        Project project1 = new Project("新華城1",
                ISO_DATE_FORMAT.parse(startTime1), ISO_DATE_FORMAT.parse(endTime1));
        Project project2 = new Project("新華城2",
                ISO_DATE_FORMAT.parse(startTime2), ISO_DATE_FORMAT.parse(endTime2));
        Project project3 = new Project("新華城3",
                ISO_DATE_FORMAT.parse(startTime3), ISO_DATE_FORMAT.parse(endTime3));
        List projects = new ArrayList<>();
        projects.add(project1);
        projects.add(project2);
        projects.add(project3);

//            因為測試所用,上面的一般都是從數據庫讀出來,封裝好的數據,真正的項目中不會這樣寫。
        List jsonObjects = LambdaUtil.simpleMap(projects, t -> {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("name", t.getName());
            LambdaUtil.ifNotNullThen(t.getStartTime(), x -> jsonObject.put("startTime", ISO_DATE_FORMAT.format(x)));
            LambdaUtil.ifNotNullThen(t.getEndTime(), x -> jsonObject.put("endTime",ISO_DATE_FORMAT.format(x)));
            jsonObject.put("validateTime", jsonObject.getString("startTime") + " - " + jsonObject.getString("endTime"));
            jsonObject.remove("startTime");
            jsonObject.remove("endTime");
            return jsonObject;
        });
        System.out.println(jsonObjects);

    } catch (ParseException e) {
        e.printStackTrace();
    }

如果,我們不使用lambda表達式,來書寫上面的代碼,會變得非常大的臃腫。然而,真正的項目不會這樣寫,數據一般都從數據庫讀出來,然后,再用過濾的方法進行過濾,如下面的代碼:

/**
 * Created By zby on 20:16 2019/1/2
 * 展示列表
 */
@RequestMapping(value = "/list/{id}", method = RequestMethod.GET)
public Result listProjectProcess(@PathVariable Long id) {
    String[] PRO_JSON = {"processId", "dictCode", "dictValue", "opTime", "isChecked"};
    List projectProcessDataList = projectProcessService.listProjectProcess(id).getResultData();
    List process = simpleMap(projectProcessDataList.subList(0, projectProcessDataList.size() - 3), x -> {
        JSONObject json = propsFilter(x, PRO_JSON);
        ifNotNullThen(x.getOpTime(), t -> json.replace("opTime", t.substring(0, t.indexOf("."))));
        return json;
    });
    Project project = projectService.get(id).getResultData();
    JSONObject body = new JSONObject();
    body.put("projectProcess", process);
    body.put("resultSummary", project.getResultSummary());
    return ResultUtil.buildSuccess(body);
}

這才是真正的項目中使用的lambdaUtil,一般,我們會有架構師將操作lambda表達式方法封裝成LambdaUtil類,我們只要在里面填充數據即可。

當然,既然是集合,自然就有集合的排序,雖然,我們會在數據庫中排好序,再通過框架的list方法,返回出去,但是,對于枚舉的排序集合,還是能夠用的到的。

排序的lambda

此外,還回頭集合排序的LambdaUtil方法,這個一般很少用,知道就可以了。

 public static  List simpleSort(Collection collection, Comparator comparator) {
    if (isNull(collection)) return null;
    return collection.stream().sorted(comparator).collect(toList());
}
總結

知己知彼,百戰不殆。往架構師的方向又邁進了一步!!!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102817.html

相關文章

  • 業級lambda達式你對lambda更好理解

    摘要:但,如果加入了函數式編程,也就是將方法作為形參傳遞,這必然讓開發者為難。但是,其他語言早就使用了函數式編程,比如最常見腳本語言。這就是函數式編程,傳遞的是一個函數直到,才引用了函數式編程,也就是我們所說的表達式。 導讀 Java從jdk1發展到今天,方法的形參類型可以是基本變量,可以是jdk自帶的類型,也可以是用戶自定義的類型,但是,方法能不能作為形參來傳遞?我們希望java能夠像其他...

    SegmentFault 評論0 收藏0
  • 《Java8實戰》-第三章讀書筆記(Lambda達式-02)

    摘要:上下文比如,接受它傳遞的方法的參數,或者接受它的值得局部變量中表達式需要類型稱為目標類型。但局部變量必須顯示的聲明,或實際上就算。換句話說,表達式只能捕獲指派給它們的局部變量一次。注捕獲實例變量可以被看作捕獲最終局部變量。 由于第三章的內容比較多,而且為了讓大家更好的了解Lambda表達式的使用,也寫了一些相關的實例,可以在Github或者碼云上拉取讀書筆記的代碼進行參考。 類型檢查、...

    iflove 評論0 收藏0
  • Java 8Lambda及其在Android 開發中應用

    摘要:由此可以看出,使用可以讓你的代碼在某些情況下達到何等的簡潔。如果沒有參數,那么前面的是必須存在的。我們知道中的,而其實就是一個只定義了一個抽象方法的。也就是說,可以訪問定義它的那個方法的局部變量。而在里面,還可以訪問所謂的局部變量。 上次在盆友圈發了一張照片 showImg(http://chriszou.com/images/lambda_example.png); 上面的兩段代碼是...

    liuhh 評論0 收藏0
  • Java 8之方法引用和Lambda達式

    摘要:方法引用在之前只能進行值傳遞,方法是不能傳遞的。首先方法接受了一個類型的對象,方法是獲取所有的文件,是用來存儲篩選之后的元素,循環所有獲得到的文件數組,然后調用中的方法來進行條件篩選,放入后返回。 方法引用: 在Java 8之前只能進行值傳遞,方法是不能傳遞的。如果你想調用一個方法你必須先獲取到它所在的類的實例,然后再通過實例去調用這個方法,但是Java 8新增了方法引用這個新特性可以...

    legendmohe 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<