使用TreeMap排序问题

时间:2011-02-17 20:16:03

标签: java collections

我正在尝试在HashMap中放置一些键值,然后尝试使用TreeMap进行排序,如下所示。问题是如果地图中有相似的值,那么在排序后它会考虑其中任何一个。

   import java.util.*;

public class HashmapExample {

            public static void main(String[] args) {

            HashMap<String,Integer> map = new HashMap<String,Integer>();
            ValueComparator bvc =  new ValueComparator(map);
            TreeMap<String,Integer> sorted_map = new TreeMap(bvc);

            map.put("A",99);
            map.put("B",67);
            map.put("C",123);
            map.put("G",67);
            map.put("F",67);
            map.put("H",67);
            map.put("D",6);

            System.out.println("unsorted map");
            for (String key : map.keySet()) {
                System.out.println("key/value: " + key + "/"+map.get(key));
            }

            sorted_map.putAll(map);

            System.out.println("results after sorting");
            for (String key : sorted_map.keySet()) {
                System.out.println("key/value: " + key + "/"+sorted_map.get(key));
            }
        }

    }

    class ValueComparator implements Comparator {

      Map base;
      public ValueComparator(Map base) {
          this.base = base;
      }

      public int compare(Object a,Object b) {

        if((Integer)base.get(a) > (Integer)base.get(b)) {
          return 1;
        } else if((Integer)base.get(a) == (Integer)base.get(b)) {
          return 0;
        } else {
          return -1;
        }
      }
    }

此后输出如下

unsorted map
key/value: D/6
key/value: A/99
key/value: F/67
key/value: H/67
key/value: C/123
key/value: B/67
key/value: G/67
results after sorting
key/value: D/6
key/value: F/67
key/value: A/99
key/value: C/123

对于B,G,F和H键,我给出的值为67.在排序映射后,它仅显示F值并且消除B,G和H值。我想显示下面的输出

    key/value: D/6
    key/value: B/67
    key/value: G/67
    key/value: F/67
    key/value: H/67
    key/value: A/99
    key/value: C/123

6 个答案:

答案 0 :(得分:4)

消除键B,G和H的原因是因为您提供的比较器仅根据值进行比较。由于它们都具有相同的值,因此它们都是相等的键,这意味着将覆盖其他键。

要打印出你想要的东西,你的比较器需要首先比较这些值,然后如果它们相等,则比较这些键。

int compare(Comparable key1, Comparable key2) {
   // I'm guessing you are doing something like:
   // return map.get(key1).compareTo(map.get(key2));

    // you can change it to something like
    int result = key1.compareTo(key2);
    if ( result == 0 ) {
      result= key1.compareTo(key2) 
    }

    return result;

}

答案 1 :(得分:2)

不要将TreeSet用于此目的或使其像smt一样

class ValueComparator implements Comparator<String> {
    private final Map<String, Integer> base;

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

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

答案 2 :(得分:1)

TreeSet删除重复项,即compareTo()== 0。

我建议你让比较器在值相同时比较键,你应该得到。

key/value: D/6
key/value: B/67
key/value: F/67
key/value: G/67
key/value: H/67
key/value: A/99
key/value: C/123

答案 3 :(得分:1)

正如大家都说的那样,比较代码已被破坏。用它替换它。这不会考虑具有相同值的两对,但是不同的键,相等。

  public int compare(Object a,Object b) {

    if((Integer)base.get(a) > (Integer)base.get(b)) {
      return 1;
    } else if((Integer)base.get(a) == (Integer)base.get(b)) {
      return ((String)a).compareTo((String)b);
    } else {
      return -1;
    }

  }

答案 4 :(得分:0)

您的比较器有问题。例如比较方法为G和F返回0.因此树图没有与其中一个关联的键值对。

你需要处理比较器。

答案 5 :(得分:0)

根据杰夫的回答,我写了一个通用版本:

public class MapValueComparator<K extends Comparable<K>, V extends Comparable<V>> implements Comparator<K> {
    private final Map<K, V> base;
    private final boolean ascending;

    public MapValueComparator(Map<K, V> base) {
        this.base = base;
        this.ascending = true;
    }

    public MapValueComparator(Map<K, V> base, boolean ascending) {
        this.base = base;
        this.ascending = ascending;
    }

    @Override
    public int compare(K a, K b) {
        int r = base.get(a).compareTo(base.get(b));
        if (r == 0)
            r = a.compareTo(b);

        if (ascending)
            return r;
        else
            return -r;
    }
}

可以按如下方式使用:

Map<String,Integer> map = new HashMap<String,Integer>();
// add some contents to map ...

MapValueComparator<String, Integer> mvc = new MapValueComparator<String, Integer>(map);
TreeMap<String, Integer> sorted_map = new TreeMap<String, Integer>(mvc);
sorted_map.putAll(map);