亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Map<K,V> 在按值分組后返回到 Map<V,Map<K,V>>

Map<K,V> 在按值分組后返回到 Map<V,Map<K,V>>

慕無忌1623718 2022-12-15 10:47:47
我正在努力維護我想要的跨 Java 流操作的數據結構,這很可能是由于缺乏適當的理解和實踐。public class Main {    public static void main(String[] args) {        List<Integer> list = Arrays.asList(1, 1, 1, 2, 3, 3, 3, 3);            //Group by            Map <Integer, Long> countGrouped = list.stream().collect(                    Collectors.groupingBy(                            x -> x, Collectors.counting()));            System.out.println("group by value, count " + countGrouped);            //Sort desc            Map <Integer, Long> descendingSorted = new LinkedHashMap<>();            countGrouped.entrySet().stream()                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))                .forEachOrdered(x -> descendingSorted.put(x.getKey(), x.getValue()));            System.out.println("sorted " + descendingSorted);            //filter            Map <Integer, Long> filtered = new LinkedHashMap<>();            descendingSorted.entrySet().stream()                .filter(x -> x.getValue() >= 2)                .forEach(x -> filtered.put(x.getKey(), x.getValue()));;            System.out.println("filtered " + filtered);            //Split groups            Map<Object, List<Entry<Integer, Long>>> groups = filtered.entrySet().stream()                    .collect(Collectors.groupingBy(x -> x.getValue()));            System.out.println("grouped " + groups);    }}導致group by value, count {1=3, 2=1, 3=4}sorted {3=4, 1=3, 2=1}filtered {3=4, 1=3}grouped {3=[1=3], 4=[3=4]}這是正確的,但正如您所看到的,我正在逐漸進入更深奧的數據結構,沒有特別的意義,如您所見,以(wtf?)結束Map<Object, List<Entry<Integer, Long>>>。雖然它可以只是一個Map<Int, Map<Int, Int>>.所以具體問題是,如何轉換和包含流操作產生的數據結構輸出?我已經看到 Collectors 提供了對 Map(...) 的轉換操作,我想這是要走的路,但我無法(我認為是由于缺乏適當的知識)讓它工作。在這種情況下,在我看來,教學解釋、鏈接到綜合資源以更好地理解流和函數式編程或類似的東西,比針對特定情況的實際解決方案更有幫助(這對一個練習,但你明白了)
查看完整描述

2 回答

?
www說

TA貢獻1775條經驗 獲得超8個贊

你在這里遇到困難有點令人驚訝,因為你已經展示了所有必要事物的知識。您知道groupingBy可以取另一個Collector,您toMap已經命名了正確的,并且您已經使用函數來提取Map.Entry值。


結合這些東西,給你


Map<Long, Map<Integer, Long>> groups = filtered.entrySet().stream()

    .collect(Collectors.groupingBy(x -> x.getValue(),

        Collectors.toMap(x -> x.getKey(), x -> x.getValue())));

System.out.println("grouped " + groups);

為了更好地演示操作,我將輸入更改為


List<Integer> list = Arrays.asList(1, 1, 1, 2, 3, 3, 3, 3, 4, 4, 4);

這導致


grouped {3=[1=3, 4=3], 4=[3=4]}

但是,重復始終與外部映射鍵相同的計數是沒有意義的。所以另一種選擇是


Map<Long, List<Integer>> groups = filtered.entrySet().stream()

    .collect(Collectors.groupingBy(Map.Entry::getValue,

        Collectors.mapping(Map.Entry::getKey, Collectors.toList())));

System.out.println("grouped " + groups);

這導致


grouped {3=[1, 4], 4=[3]}

請注意,您不應將forEach/forEachOrdered用于put映射。您的中間步驟應該是


//Sort desc

Map<Integer, Long> descendingSorted = countGrouped.entrySet().stream()

    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))

    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,

        (a,b) -> { throw new AssertionError(); }, LinkedHashMap::new));

System.out.println("sorted " + descendingSorted);


//filter

Map<Integer, Long> filtered = descendingSorted.entrySet().stream()

    .filter(x -> x.getValue() >= 2)

    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,

        (a,b) -> { throw new AssertionError(); }, LinkedHashMap::new));

System.out.println("filtered " + filtered);

接受地圖工廠的toMap收集器迫使我們提供合并功能,但由于我們的輸入已經是一個必須具有不同鍵的地圖,我在這里提供了一個始終拋出的功能,因為如果出現重復項,就會出現嚴重錯誤。


但請注意,強制所有這些操作收集到新地圖中是不必要的復雜和低效的。首先對整個數據進行排序并filter隨后減少數據量也沒有意義。首先過濾可能會減少排序步驟的工作,而過濾操作的結果不應取決于順序。


在單個管道中完成整個操作要好得多


List<Integer> list = Arrays.asList(1, 1, 1, 2, 3, 3, 3, 3, 4, 4, 4);


Map<Integer, Long> countGrouped = list.stream().collect(

    Collectors.groupingBy(x -> x, Collectors.counting()));

System.out.println("group by value, count " + countGrouped);


Map<Long, List<Integer>> groups = countGrouped.entrySet().stream()

    .filter(x -> x.getValue() >= 2)

    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))

    .collect(Collectors.groupingBy(Map.Entry::getValue, LinkedHashMap::new, 

        Collectors.mapping(Map.Entry::getKey, Collectors.toList())));


System.out.println("grouped " + groups);

請注意,與之前的代碼不同,現在最后的分組操作也會保留順序,從而導致


grouped {4=[3], 3=[1, 4]}

即,組按計數降序排序。


由于計數是結果映射的鍵,我們還可以使用本質上排序的映射作為結果類型并省略排序步驟:


Map<Long, List<Integer>> groups = countGrouped.entrySet().stream()

    .filter(x -> x.getValue() >= 2)

    .collect(Collectors.groupingBy(Map.Entry::getValue,

        () -> new TreeMap<>(Comparator.<Long>reverseOrder()),

        Collectors.mapping(Map.Entry::getKey, Collectors.toList())));

主要區別在于流操作后結果映射的行為,例如,如果您向其中插入更多元素,因為TreeMap將根據降序插入新鍵,而LinkedHashMap將它們追加到末尾,保持插入順序。


查看完整回答
反對 回復 2022-12-15
?
神不在的星期二

TA貢獻1963條經驗 獲得超6個贊

的簽名groupingBy是public static <T, K> Collector<T, ?, Map<K, List<T>>>

    groupingBy(Function<? super T, ? extends K> classifier),但如果我理解正確,您只想將值映射到地圖條目,例如:


Map<Object, Map.Entry<Integer, Long>> groups = filtered.entrySet().stream()

        .collect(Collectors.toMap(Map.Entry::getValue, x -> x));

System.out.println("grouped " + groups);

輸出


grouped {3=1=3, 4=3=4}


查看完整回答
反對 回復 2022-12-15
  • 2 回答
  • 0 關注
  • 148 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號