天天看點

java 8 lambda表達式list操作分組、過濾、求和、最值、排序、去重,交集、并集、差集、去重并集lambda表達式

描述:java8的lambda表達式提供了一些友善list操作的方法,主要涵蓋分組、過濾、求和、最值、排序、去重。跟之前的傳統寫法對比,能少寫不少代碼。

lambda表達式

實體

package com.vvvtimes.vo;
 
import java.math.BigDecimal;
import java.util.Date;
 
public class User {
 
    private Long id;
 
    //姓名
    private String name;
 
    //年齡
    private int age;
 
    //工号
    private String jobNumber;
 
    //性别
    private String sex;
 
    //入職日期
    private Date entryDate;
 
    //家庭成員數量
    private BigDecimal familyMemberQuantity;
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public String getJobNumber() {
        return jobNumber;
    }
 
    public void setJobNumber(String jobNumber) {
        this.jobNumber = jobNumber;
    }
 
    public String getSex() {
        return sex;
    }
 
    public void setSex(String sex) {
        this.sex = sex;
    }
 
    public Date getEntryDate() {
        return entryDate;
    }
 
    public void setEntryDate(Date entryDate) {
        this.entryDate = entryDate;
    }
 
    public BigDecimal getFamilyMemberQuantity() {
        return familyMemberQuantity;
    }
 
    public void setFamilyMemberQuantity(BigDecimal familyMemberQuantity) {
        this.familyMemberQuantity = familyMemberQuantity;
    }
}
           

1.分組

通過groupingBy可以分組指定字段

//分組
        Map<String, List<User>> groupBySex = userList.stream().collect(Collectors.groupingBy(User::getSex));
        //周遊分組
        for (Map.Entry<String, List<User>> entryUser : groupBySex.entrySet()) {
            String key = entryUser.getKey();
            List<User> entryUserList = entryUser.getValue();
           

2.過濾

通過filter方法可以過濾某些條件

//過濾
        //排除掉工号為201901的使用者
        List<User> userCommonList = userList.stream().filter(a -> !a.getJobNumber().equals("201901")).collect(Collectors.toList());
           

3.求和

分基本類型和大數類型求和,基本類型先mapToInt,然後調用sum方法,大數類型使用reduce調用BigDecimal::add方法

//求和
        //基本類型
        int sumAge = userList.stream().mapToInt(User::getAge).sum();
        //BigDecimal求和
        BigDecimal totalQuantity = userList.stream().map(User::getFamilyMemberQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
           

上面的求和不能過濾bigDecimal對象為null的情況,可能會報空指針,這種情況,我們可以用filter方法過濾,或者重寫求和方法

重寫求和方法

package com.vvvtimes.util;
 
import java.math.BigDecimal;
 
public class BigDecimalUtils {
 
    public static BigDecimal ifNullSet0(BigDecimal in) {
        if (in != null) {
            return in;
        }
        return BigDecimal.ZERO;
    }
 
    public static BigDecimal sum(BigDecimal ...in){
        BigDecimal result = BigDecimal.ZERO;
        for (int i = 0; i < in.length; i++){
            result = result.add(ifNullSet0(in[i]));
        }
        return result;
    }
}
           

使用重寫的方法

BigDecimal totalQuantity2 = userList.stream().map(User::getFamilyMemberQuantity).reduce(BigDecimal.ZERO, BigDecimalUtils::sum);

           

判斷對象空

stream.filter(x -> x!=null)
           
stream.filter(Objects::nonNull)
           

判斷字段空

stream.filter(x -> x.getDateTime()!=null)
           

4.最值

求最小與最大,使用min max方法

//最小
        Date minEntryDate = userList.stream().map(User::getEntryDate).min(Date::compareTo).get();
 
        //最大
        Date maxEntryDate = userList.stream().map(User::getEntryDate).max(Date::compareTo).get();
           

5.List 轉map

/**
         * List -> Map
         * 需要注意的是:
         * toMap 如果集合對象有重複的key,會報錯Duplicate key ....
         *  user1,user2的id都為1。
         *  可以用 (k1,k2)->k1 來設定,如果有重複的key,則保留key1,舍棄key2
         */
        Map<Long, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, a -> a,(k1,k2)->k1));
           

6.排序

可通過Sort對單字段多字段排序

//排序
        //單字段排序,根據id排序
        userList.sort(Comparator.comparing(User::getId));
        //多字段排序,根據id,年齡排序
        userList.sort(Comparator.comparing(User::getId).thenComparing(User::getAge));
           

7.去重

可通過distinct方法進行去重

//去重
        List<Long> idList = new ArrayList<Long>();
        idList.add(1L);
        idList.add(1L);
        idList.add(2L);
        List<Long> distinctIdList = idList.stream().distinct().collect(Collectors.toList());
           

8.擷取list某個字段組裝新list

//擷取list對象的某個字段組裝成新list
        List<Long> userIdList = userList.stream().map(a -> a.getId()).collect(Collectors.toList());
           

9.list 交集/并集/差集/去重并集

import static java.util.stream.Collectors.toList;
import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {
        List<String> list1 = new ArrayList();
        list1.add("1111");
        list1.add("2222");
        list1.add("3333");

        List<String> list2 = new ArrayList();
        list2.add("3333");
        list2.add("4444");
        list2.add("5555");

        // 交集 	拓展:list2裡面如果是對象,則需要提取每個對象的某一屬性組成新的list,多個條件則為多個list
        List<String> intersection = list1.stream().filter(item -> list2.contains(item)).collect(Collectors.toList());
        System.out.println("---得到交集 intersection---");
        intersection.parallelStream().forEach(System.out :: println);

        // 差集 (list1 - list2)	同上拓展
        List<String> reduce1 = list1.stream().filter(item -> !list2.contains(item)).collect(Collectors.toList());
        System.out.println("---得到差集 reduce1 (list1 - list2)---");
        reduce1.parallelStream().forEach(System.out :: println);

        // 差集 (list2 - list1)
        List<String> reduce2 = list2.stream().filter(item -> !list1.contains(item)).collect(Collectors.toList());
        System.out.println("---得到差集 reduce2 (list2 - list1)---");
        reduce2.parallelStream().forEach(System.out :: println);

        // 并集
        List<String> listAll = list1.parallelStream().collect(toList());
        List<String> listAll2 = list2.parallelStream().collect(Collectors.toList());
        listAll.addAll(listAll2);
        System.out.println("---得到并集 listAll---");
        listAll.parallelStream().forEach(System.out :: println);

        // 去重并集
        List<String> listAllDistinct = listAll.stream().distinct().collect(Collectors.toList());
        System.out.println("---得到去重并集 listAllDistinct---");
        listAllDistinct.parallelStream().forEach(System.out :: println);

        System.out.println("---原來的List1---");
        list1.parallelStream().forEach(System.out :: println);
        System.out.println("---原來的List2---");
        list2.parallelStream().forEach(System.out :: println);

        // 一般有filter 操作時,不用并行流parallelStream ,如果用的話可能會導緻線程安全問題

    }
}