java8 小技巧保證分組groupingBy后排序不變


問題:
遇到一個小問題,查詢出來一組數據后,按照其中的屬性進行groupBy 分組 ,分組后要保證順序不變。但是實際用groupBy進行分組后,返回的數據是雜亂無章的,沒有按照原來list 的順序返回

排查
首先去api中查找解決,查看Java 的 java.util.stream 包 Collectors 類 groupingBy 方法實現,結果如下:

//一個參數
   public static <T, K> Collector<T, ?, Map<K, List<T>>>
    groupingBy(Function<? super T, ? extends K> classifier) {
        return groupingBy(classifier, toList());
    }

//兩個參數
    public static <T, K, A, D>
    Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
                                          Collector<? super T, A, D> downstream) {
        return groupingBy(classifier, HashMap::new, downstream);
    }
    
//三個參數
  public static <T, K, D, A, M extends Map<K, D>>
    Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
                                  Supplier<M> mapFactory,
                                  Collector<? super T, A, D> downstream) {......}

通過java api 發現 groupingBy 調用是內部自己創建了一個 HashMap ( HashMap::new)。因為 hashMap,是無無序的,是根據key的hashcode進行hash,然后放入對應的地方。所以在按照一定順序put進HashMap中,然后遍歷出HashMap的順序跟put的順序不同。

知道這個了就明白了為什么無序了。所以我們直接調用三個參數的 groupingBy 方法mapFactory ,傳入有順序的Map, LinkedHashMap 就可以了。

關於 LinkedHashMap 的信息自行百度

解決
創建Person數據集合,然后按照年齡排序,排序后進行分組,保證分組后順序不變。

//創建數據
 private static List<Person> getPersionList() {
        List<Person> persons = new ArrayList<>();
        for (int i = 1; i <= 40; i++) {
            Random r = new Random();
            Person person = new Person();
            person.setName("abel-" + i);
            person.setSex((int) (Math.random() * 2));
            person.setGroup(String.valueOf(i%2));
            person.setAge(25 + r.nextInt(50));
            persons.add(person);
        }
        return persons;

    }


    /**
     * 分組
     */
    private static void groupByTest() {
        List<Person> persons = getPersionList();
        //將list 排序,並按照排序后的結果進行有序分組
        LinkedHashMap<Integer, List<Person>> ageMap = personsSort.stream().sorted(Comparator.comparingInt(Person::getAge)).collect(Collectors.groupingBy(Person::getAge, LinkedHashMap::new, Collectors.toList()));
    }

關於 排序Comparator.comparingInt 參考:
https://www.jianshu.com/p/3f621e51f3


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM