Проблема сортировки с использованием TreeMap - PullRequest
3 голосов
/ 17 февраля 2011

Я пытаюсь поместить некоторые ключевые значения в 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 ]

4 голосов
/ 17 февраля 2011

Причина, по которой клавиши 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;

}
2 голосов
/ 17 февраля 2011

Не используйте 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;
        }
    }
}
1 голос
/ 17 февраля 2011

Как все говорили, ваш код сравнения не работает. Замените это на это. Это не будет рассматривать две пары с одинаковым значением, но разные ключи, равными.

  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;
    }

  }
1 голос
/ 17 февраля 2011

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
0 голосов
/ 17 июля 2012

Основываясь на ответе Джеффа, я написал общую версию:

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);
0 голосов
/ 17 февраля 2011

Ваш компаратор имеет проблемы. например Метод сравнения возвращает 0 для G и F. Следовательно, древовидная карта не имеет пары ключ-значение, связанной с одним из них.

Вам нужно работать на компараторе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...