簡體   English   中英

Java Map按值排序

[英]Java Map sort by value

我正在尋找按值排序Map<String, Integer>的方法。 我發現這篇文章解決了我的排序問題,但並不完全正確。 根據帖子,我寫了以下代碼:

import java.util.*;

public class Sort {

    static class ValueComparator implements Comparator<String> {

        Map<String, Integer> base;

        ValueComparator(Map<String, Integer> base) {
            this.base = base;
        }

        @Override
        public int compare(String a, String b) {
            if (base.get(a) >= base.get(b)) {
                return 1;
            } else {
                return -1;
            }
        }
    }

    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        ValueComparator vc = new ValueComparator(map);
        TreeMap<String, Integer> sorted = new TreeMap<String, Integer>(vc);
        map.put("A", 1);
        map.put("B", 2);
        sorted.putAll(map);
        for (String key : sorted.keySet()) {
            System.out.println(key + " : " + sorted.get(key)); // why null values here?
        }
        System.out.println(sorted.values()); // But we do have non-null values here!
    }
}

輸出:

A : null
B : null
[1, 2]
BUILD SUCCESSFUL (total time: 0 seconds)

從輸出中可以看出, get方法始終返回null 原因是我的ValueComparator.compare()方法永遠不會返回0 ,這是我通過發布這篇文章得出的。

有人在該帖子中建議以下解決null值問題:

        public int compare(String a, String b) {
            if (base.get(a) > base.get(b)) {
                return 1;
            }else if(base.get(a) ==  base.get(b)){
                return 0;
            }
            return -1;  
        }

我測試了這段代碼,它引入了一個關鍵的合並問題。 換句話說,當值相等時,它們的相應鍵被合並。

我也嘗試過以下方法:

            public int compare(String a, String b) {
                if (a.equals(b)) return 0;
                if (base.get(a) >= base.get(b)) {
                    return 1;
                } else return -1;
            }

它也不起作用。 某些值仍為null 此外,此解決方法可能存在邏輯問題。

有人可以為我的問題提出一個完全可行的解決方案 我希望按值函數排序工作, get方法同時工作。

在比較函數中,當值相等時,您應該比較鍵。 這將確保具有相同值的不同密鑰不會被“合並”,因為它消除了否則將比較相等的條目。

例如:

    @Override
    public int compare(String a, String b) {
        Integer x = base.get(a);
        Integer y = base.get(b);
        if (x.equals(y)) {
            return a.compareTo(b);
        }
        return x.compareTo(y);
    }

(您需要修改上面的代碼以匹配您的空值策略)

請注意,您對值進行排序的方法非常脆弱。 您的“已排序”地圖將不支持添加新條目,這可能會令人困惑。

base.get(a) ==  base.get(b)

此代碼通過引用比較盒裝的Integer

將它更改為base.get(a).equals(base.get(b)) ,它應該工作。

試試這個:

return base.get(a).compareTo(base.get(b));

要證明您對自動取消裝箱不正確:

Integer a = new Integer(2);
Integer b = new Integer(2);
boolean isEqual = ( a == b );
System.out.println("equal: " + isEqual);
System.out.println("a: " + a);
System.out.println("b: " + b);

我的輸出是:

equal: false
a: 2
b: 2

試試這個 ...

HashMap<String, Integer> h = new HashMap<String, Integer>();
h.put("z",30);
h.put("e",10);
h.put("b",20);
h.put("c",20);
List<Map.Entry> a = new ArrayList<Map.Entry>(h.entrySet());
Collections.sort(a,
         new Comparator() {
             public int compare(Object o1, Object o2) {
                 Map.Entry e1 = (Map.Entry) o1;
                 Map.Entry e2 = (Map.Entry) o2;
                 return ((Comparable) e1.getValue()).compareTo(e2.getValue());
             }
         });

for (Map.Entry e : a) {
        System.out.println(e.getKey() + " " + e.getValue());
}

Ouptut:

e 10
b 20
c 20
z 30

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM