当两个以上的值具有相同的排序属性时,按值排序Java TreeMap不起作用

vpk*_*vpk 2 java sorting treemap

我想基于某些属性值对Java TreeMap进行排序.具体来说,我想TreeMap<Integer, Hashset<Integer>>根据大小来排序Hashset<Integer>.为实现这一目标,我做了以下工作:

比较类:

private static class ValueComparer implements Comparator<Integer> {
    private Map<Integer, HashSet<Integer>>  map = null;
    public ValueComparer (Map<Integer, HashSet<Integer>> map){
        super();
        this.map = map;
    }

@Override
    public int compare(Integer o1, Integer o2) {
        HashSet<Integer> h1 = map.get(o1);
        HashSet<Integer> h2 = map.get(o2);

        int compare = h2.size().compareTo(h1.size());

        if (compare == 0 && o1!=o2){
            return -1;
        }
        else {
            return compare;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

一个用法示例:

TreeMap<Integer, HashSet<Integer>> originalMap = new TreeMap<Integer, HashSet<Integer>>();

//load keys and values into map

ValueComparer comp = new ValueComparer(originalMap);
TreeMap<Integer, HashSet<Integer>> sortedMap = new TreeMap<Integer, HashSet<Integer>>(comp);
sortedMap.putAll(originalMap);
Run Code Online (Sandbox Code Playgroud)

问题:

originalMap包含两个以上相同大小的值时,这不起作用.对于其他情况,它可以正常工作.当映射中的两个以上的值具有相同的大小时,新的sorted-map中的第三个值为null,并在我尝试访问它时抛出NullPointerException.

我无法弄清楚问题是什么.如果有人能指出,那就好了.

更新: 这是一个在两个值具有相同大小时有效的示例:http://ideone.com/iFD9c 在上面的示例中,如果取消注释第52-54行,则此代码将失败 - 这就是我的问题所在.

dac*_*cwe 7

更新:你不能返回-1ValueComparator只是因为你想避免不被删除重复键.检查合同Comparator.compare.


当您传递ComparatorTreeMap您时,计算一个("新")位置来放置该条目.没有(计算)密钥可以在a中存在多次TreeMap.


如果要对orginalMap值的大小进行排序,可以按如下方式进行排序:

public static void main(String[] args) throws Exception {

    TreeMap<Integer, HashSet<Integer>> originalMap = 
        new TreeMap<Integer, HashSet<Integer>>();

    originalMap.put(0, new HashSet<Integer>() {{ add(6); add(7); }});
    originalMap.put(1, new HashSet<Integer>() {{ add(6); }});
    originalMap.put(2, new HashSet<Integer>() {{ add(9); add(8); }});


    ArrayList<Map.Entry<Integer, HashSet<Integer>>> list = 
        new ArrayList<Map.Entry<Integer, HashSet<Integer>>>();
    list.addAll(originalMap.entrySet());

    Collections.sort(list, new Comparator<Map.Entry<Integer,HashSet<Integer>>>(){
        public int compare(Map.Entry<Integer, HashSet<Integer>> o1,
                           Map.Entry<Integer, HashSet<Integer>> o2) {

            Integer size1 = (Integer) o1.getValue().size();
            Integer size2 = (Integer) o2.getValue().size();
            return size2.compareTo(size1);
        }
    });

    System.out.println(list);
}
Run Code Online (Sandbox Code Playgroud)

  • 哎呀,从你的`Comparator`返回`-1`以避免重复的条目被删除不是合同的方式[`Comparator.compare`](http://download.oracle.com/javase/6/docs/指定了api/java/util/Comparator.html#compare%28T,%20T%29).你不能那样做!(更新的答案) (2认同)
  • 从api文档:**实现者必须确保所有x和y的sgn(compare(x,y))== -sgn(compare(y,x)).**如果你总是返回`-1`相同的尺寸然后你打破了这个属性. (2认同)