TreeMap <integer,integer =“”>删除不工作</integer,>

时间:2014-01-14 16:45:28

标签: java

我试图通过执行这个循环来获取TreeMap的前10个元素:

        TreeMap<Integer, Integer> sortedMap = sortMap(m);
        String outString = "";
        int count = 10;
        while (count > 0) {
            count--;
            Integer k = sortedMap.firstKey();
            outString += String.valueOf(k);
            sortedMap.remove(k);
            if (count != 0) {
                outString += ",";
            }
        }

        System.out.println("outVal is " + outVal);

这会打印outVal is 11377,11377,11377,11377,11377,11377,11377,11377,11377,11377 Integer实施Comparable,那么为什么remove无法正常工作?

更新以下是我的sortMap实施:

        public static TreeMap<Integer, Integer> sortMap(HashMap<Integer, Integer> map) {
           ValueComparator bvc =  new ValueComparator(map);
           TreeMap<Integer,Integer> sorted_map = new TreeMap<Integer,Integer>(bvc);
           sorted_map.putAll(map);
           return sorted_map;
        }

class ValueComparator implements Comparator<Integer> {
    java.util.Map<Integer, Integer> base;
    public ValueComparator(java.util.Map<Integer, Integer> base) {
        this.base = base;
    }

    // Note: this comparator imposes orderings that are inconsistent with equals.    
    public int compare(Integer a, Integer b) {
        if (base.get(a) >= base.get(b)) {
            return -1;
        } else {
            return 1;
        } // returning 0 would merge keys
    }
}

更新这很有用:Java Map sort by value

3 个答案:

答案 0 :(得分:5)

public int compare(Integer a, Integer b) {
    if (base.get(a) >= base.get(b)) {
        return -1;
    } else {
        return 1;
    } // returning 0 would merge keys
}

这个比较器存在缺陷(除了它与equals不一致外)它不符合比较器合同,该合同规定compare(a,b) > 0暗示compare(b,a) < 0,反之亦然。由于TreeMap依赖于比较器返回0来找到你试图remove()的密钥,它将永远无法移除任何东西 - 无论你尝试什么密钥并且搜索地图都不会想到密钥存在。

答案 1 :(得分:4)

编辑后很明显,您的自定义比较器是罪魁祸首。你真正想要实现的是在地图中收集十个最高的键。

但是,如果我可以说,你的方法是不必要的迂回。您已经有了一些地图m,这是您的起点。所以你需要的只是收集它的entrySet,按值排序,并采取前十个元素:

import java.util.Map.Entry;

final List<Entry<Integer,Integer>> list = new ArrayList<>(m.entrySet());
Collections.sort(list, new Comparator<Entry<Integer, Integer>>() {
  @Override public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2) {
    return o1.getValue().compareTo(o2.getValue());
  }});
final StringBuilder b = new StringBuilder();
String delimiter = "";
for (Entry<Integer, Integer> e : list.subList(0, 10)) {
  b.append(delimiter).append(e.getKey());
  delimiter = ",";
}
System.out.println(b);

请注意,一次性排序比将元素逐个插入二叉搜索树更有效。

我也在使用StringBuilder,这比在每一步中重新创建一个完整的String更有效。

答案 2 :(得分:0)

我试着跟着它为我工作

    TreeMap<Integer, Integer> sortedMap = new TreeMap<>();
    String outString = "";
    sortedMap.put(1, 10);
    sortedMap.put(2, 20);
    sortedMap.put(3, 30);
    sortedMap.put(4, 40);
    sortedMap.put(5, 50);
    int count = 5;
    while (count > 0) {
        count--;
        Integer k = sortedMap.firstKey();
        outString += sortedMap.get(k);//String.valueOf(k);
        sortedMap.remove(k);
        if (count != 0) {
            outString += ",";
        }
    }

    System.out.println("outVal is " + outString);
    System.out.println(sortedMap.size());