1. 程式人生 > 其它 >JAVA8新特性之List的各種用法(最大、最小、平均值、分組、求和、遍歷、過濾、排序)

JAVA8新特性之List的各種用法(最大、最小、平均值、分組、求和、遍歷、過濾、排序)

構建一個User實體類供演示

public class Users {

    /**
     * ID
     */
    private Long id;
    /**
     * 使用者名稱
     */
    private String name;
    /**
     * 年齡
     */
    private int age;
    /**
     * 工號
     */
    private String jobNumber;
    /**
     * 性別
     */
    private String sex;
    /**
     * 註冊時間
     
*/ private Date entryDate; /** * 成員組織 */ private BigDecimal familyMemberQuantity; private Long userId; 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; } public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } @Override public String toString() { return "Users{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", jobNumber='" + jobNumber + '\'' + ", sex='" + sex + '\'' + ", entryDate=" + DateFormatUtils.format(entryDate, "yyyy-MM-dd HH:mm:ss") + ", familyMemberQuantity=" + familyMemberQuantity + '}'; } }

一、根據欄位分組得到多個List集合

構建一個產生Users的靜態法

     /**
     * 生產虛擬使用者
     *
     * @return
     */
    public static List<Users> produceUser() {
        List<Users> usersList = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            Users users = new Users();
            users.setId(Long.valueOf(i));
            users.setName("kobe" + i);
            users.setAge(15 + new Random().nextInt(5));
            users.setJobNumber("jobNumber" + i);
            if (i % 2 == 0) {
                users.setSex("男");
            } else {
                users.setSex("女");
            }
            users.setEntryDate(new Date());
            users.setFamilyMemberQuantity(new BigDecimal(i));
            usersList.add(users);
        }
        return usersList;
    }

利用Java8 特性,根據物件的某個屬性進行分組

@Test
    public void groupByGender() {
        List<Users> list = produceUser();
        // 根據性別進行分組
        Map<String, List<Users>> collect = list.stream().collect(Collectors.groupingBy(Users::getSex));
        Set<Map.Entry<String, List<Users>>> entries = collect.entrySet();
        entries.forEach(item -> {
            // 性別 男 / 女
            String gender = item.getKey();
            // 男集合 / 女集合
            List<Users> usersList = item.getValue();
            System.out.println(gender);
            usersList.forEach(user -> System.out.println(user));
        });
    }

輸出結果如下

二、集合求和

2.1 根據物件中的某個欄位求和

    /**
     * 根據年齡欄位求總和
     */
    @Test
    public void getSumByStream() {
        List<Users> list = produceUser();
        int sum = list.stream().mapToInt(Users::getAge).sum();
        System.out.println("共計:" + list.size() + "個使用者,所有年齡總和為:" + sum);
        // 求最大年齡
        Integer integer = list.stream().map(Users::getAge).max(Integer::compareTo).get();
        System.out.println(integer);
        // 得到最大年齡物件
        Users users = list.stream().max(Comparator.comparingInt(Users::getAge)).get();
        System.out.println(users);
        // 求平均年齡
        System.out.println(list.stream().mapToInt(Users::getAge).average().getAsDouble());
        // 求最大年齡
        System.out.println(list.stream().mapToInt(Users::getAge).max().getAsInt());
    }

輸出結果如下

2.2 List<數值型> 求和

    /**
     * 根據List求和
     */
    @Test
    public void getListSumByJava8() {
        List<Integer> listInt = new ArrayList();
        List<Double> listDoub = new ArrayList();
        for (int i = 0; i < 500; i++) {
            listInt.add(new Random().nextInt(1000));
            listDoub.add(new Random().nextDouble());
        }
        System.out.println("=======數值型Integer求和======");
        Integer integer = listInt.stream().reduce(Integer::sum).orElse(0);
        System.out.println(integer);
        System.out.println("=======數值型Double求和======");
        Double integer1 = listDoub.stream().reduce(Double::sum).orElse(0.00);
        System.out.println(integer1);
        // 取最大值
        System.out.println(listInt.stream().reduce(Integer::max).orElse(0));
        System.out.println(listInt.stream().mapToInt(Integer::valueOf).max().getAsInt());
        // 取最小值
        System.out.println(listInt.stream().reduce(Integer::min).orElse(0));
        // 取平均值
        System.out.println(listInt.stream().mapToInt(Integer::valueOf).average().getAsDouble());
    }

輸出結果如下

三、遍歷List集合

    /**
     * 遍歷物件
     */
    @Test
    public void traverseByJava8(){
        List<Users> list = produceUser();
        list.forEach(System.out::println);
    }

輸出結果如下

四、過濾List集合

    /**
     * 過濾物件
     */
    @Test
    public void filterByJava8() {
        List<Users> list = produceUser();
        System.out.println("原始資料為:");
        System.out.println("==============過濾後的資料為===============");
        list.forEach(System.out::println);
        //篩選出年齡大於3歲小於8歲的物件
        List<Users> collect = list.stream().filter(s -> s.getAge() > 13 && s.getAge() < 18).collect(Collectors.toList());
        System.out.println("過濾結束後的資料為:");
        collect.forEach(System.out::println);
    }

輸出結果如下

五、獲取List中的最大最小值

5.1 根據特定需求中的某個欄位求最大最小

    /**
     * 求最大最小值,根據業務型別選擇合適的型別值
     */
    @Test
    public void maxOrMinByJava8() {
        List<Users> list = produceUser();
        //根據mapTO**得到最大最小  ---寫法一
        double asDouble = list.stream().mapToDouble(Users::getAge).max().getAsDouble();
        System.out.println("將最大值轉換為Double型別進行展示,最大為:" + asDouble);
        double asDouble1 = list.stream().mapToDouble(Users::getAge).min().getAsDouble();
        System.out.println("將最小值轉換為Double型別進行展示,最小為:" + asDouble1);
        int asInt = list.stream().mapToInt(Users::getAge).max().getAsInt();
        System.out.println("將最大值轉換為Int型別進行展示,最大為:" + asInt);
        //根據map得到最大最小  ---寫法二(推薦)
        Integer integer = list.stream().map(Users::getAge).max(Integer::compareTo).get();
        System.out.println("將最大值轉換為欄位對應型別進行展示,最大為:" + integer);
        Integer integer1 = list.stream().map(Users::getAge).min(Integer::compareTo).get();
        System.out.println("將最小值轉換為欄位對應型別進行展示,最小為:" + integer1);
    }

輸出結果如下

5.2 根據特定需求中的某個欄位求平均值

    /**
     * 求最大最小值,根據業務型別選擇合適的型別值
     */
    @Test
    public void avgByJava8() {
        List<Users> list = produceUser();
        double avgAge = list.stream().mapToDouble(Users::getAge).average().getAsDouble();
        System.out.println("平均年齡為:" + avgAge);
    }

輸出結果如下

六、根據需求將List轉為Map

    /**
     * List -> Map
     * 需要注意的是:
     * toMap 如果集合物件有重複的key,會報錯Duplicate key ....
     * user1,user2的id都為1。
     * 可以用 (k1,k2)->k1 來設定,如果有重複的key,則保留key1,捨棄key2
     */
    @Test
    public void mapToListByJava8() {
        List<Users> list = produceUser();
        Map<Long, Users> map = list.stream().collect(Collectors.toMap(Users::getId, a -> a, (k1, k2) -> k1));
        for (Map.Entry<Long, Users> entry : map.entrySet()) {
            Long key = entry.getKey();
            System.out.println("map中的key是:" + key);
            System.out.println("map中的value是:" + entry.getValue().toString());
        }

        // 根據ID和年齡獲得map
        Map<Long, Integer> collect = list.stream().collect(Collectors.toMap(Users::getId, item -> Optional.ofNullable(item.getAge()).orElse(0)
                , (k1, k2) -> k1));
        System.out.println(collect.toString());
    }

輸出結果如下

七、List排序

    /**
     * 排序(單欄位/多欄位排序)
     */
    @Test
    public void sortByJava8() {
        List<Users> list = produceUser();
        System.out.println("============未排序的資料=============");
        System.out.println(list.toString());
        try {
            //單欄位排序,根據名字排序
            System.out.println("============單欄位排序,根據名字排序=============");
            list.sort(Comparator.comparing(Users::getName));
            System.out.println(list.toString());
            //多欄位排序,根據年齡再根據-->名字排序
            System.out.println("============多欄位排序,根據年齡再根據-->名字排序=============");
            list.sort(Comparator.comparing(Users::getAge, (o1, o2) -> o2 - o1).thenComparing(Users::getName));
            System.out.println(list.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

輸出結果如下

八、List去重

     /**
     * 去重
     */
    @Test
    public void distinctByJava8() {
        List<String> numList = new ArrayList();
        numList.add("kevin");
        numList.add("kevin");
        numList.add("kevin1");
        numList.add("kevin2");
        numList.add("kevin1");
        numList.add("kevin2");
        System.out.println("===========未去重的資料============");
        System.out.println(numList.toString());
        System.out.println("===========去重後的資料============");
        List<String> collect = numList.stream().distinct().collect(Collectors.toList());
        System.out.println(collect.toString());
    }

輸出結果如下

九、List的合併

首先了解下交集並集差集的概念,分別有三個區域A,B,C

9.1 List的合併之—>並集

    /**
     * 得到兩個集合的並集
     */
    @Test
    public void listByJava8() {
        List<String> list1 = new ArrayList();
        list1.add("aaa");
        list1.add("bbb");
        list1.add("ccc");
        list1.add("aaa1");
        List<String> list2 = list1;
        list2.add("ddd");
        list2.add("aaa");
        list2.add("eee");
        list2.add("ccc");
        list2.add("fff");
        list2.add("aaa1");
        list2.add("aaa2");

        //根據整個物件是否一致來去重合並得到並集
        System.out.println("==========並集: 集合A{1, 2, 3} 和集合B {2, 3, 4} 的並集是 {1, 2, 3, 4}==========");
        System.out.println("---->並集寫法一 [去重]");
        System.out.println("============並集舉例一:根據List去重特性合併多個Lits============");
        List<String> collect = Stream.of(list1, list2).flatMap(Collection::stream).distinct().collect(Collectors.toList());
        System.out.println(collect.toString());
        System.out.println("---->並集寫法二 ");
        System.out.println("============並集舉例二:根據List得到並集============");
        List<String> collect1 = list1.stream().filter(s -> list2.contains(s)).distinct().collect(Collectors.toList());
        System.out.println(collect1);
        System.out.println("==========交集: 集合A {1,2,3} 和集合B {2,3,4} 的交集為 {2,3}。即{1,2,3}∩{2,3,4}={2,3}==========");
    }

輸出結果如下

9.2 List的合併之—>交集(即兩個或多個list重複的元素的集合)

    /**
     * 得到兩個集合的交集
     */
    @Test
    public void listBingByJava8() {
        System.out.println("==========交集: 集合A {1,2,3} 和集合B {2,3,4} 的交集為 {2,3}。即{1,2,3}∩{2,3,4}={2,3}==========");
        List<String> list1 = new ArrayList();
        list1.add("aaa");
        list1.add("bbb");
        list1.add("ccc");
        list1.add("aaa1");
        List<String> list2 = list1;
        list2.add("ddd");
        list2.add("aaa");
        list2.add("eee");
        list2.add("ccc");
        list2.add("fff");
        list2.add("aaa1");
        list2.add("aaa2");
        //合併List
        List<String> collect = list1.stream().filter(s -> list2.contains(s)).collect(Collectors.toList());
        System.out.println("============多個List合併後的元資料===========");
        System.out.println(collect);
        // 獲得元素出現頻率的 Map,鍵為元素,值為元素出現的次數
        List<String> collect1 = collect.stream().collect(Collectors.toMap(a -> a, a -> 1, (a, b) -> a + b))
                //  Set<Entry>轉換為Stream<Entry>
                .entrySet().stream()
                // 過濾出元素出現次數大於 1 的 entry
                .filter(entry -> entry.getValue() > 1)
                // 獲得 entry 的鍵(重複元素)對應的 Stream
                .map(entry -> entry.getKey())
                // 轉化為 List並去重
                .distinct().collect(Collectors.toList());
        System.out.println("========合併後得到處理得到重複的資料========");
        System.out.println(collect1);
    }

輸出結果如下