Сделать компаратор TreeMap допустимым null

Этот настраиваемый компаратор значений сортирует TreeMap по его значению. Но он не допускает исключение nullpointException при поиске того, имеет ли TreeMap определенный ключ. Как изменить компаратор для обработки нулевой точки?

    import java.io.IOException;
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.TreeMap;



    public class TestTreeMap {

        public static class ValueComparator<T> implements Comparator<Object> {

            Map<T, Double> base;
            public ValueComparator(Map<T, Double> base) {
                this.base = base;
            }

            @Override
            public int compare(Object a, Object b) {
                /*if (((Double) base.get(a) == null) || ((Double) base.get(b) == null)){
                    return -1;
                }   */      
                if ((Double) base.get(a) < (Double) base.get(b)) {
                    return 1;
                } else if ((Double) base.get(a) == (Double) base.get(b)) {
                    return 0;
                } else {
                    return -1;
                }
            }

        }

        public static void main(String[] args) throws IOException { 
            Map<String, Double> tm = new HashMap<String, Double>();
            tm.put("John Doe", new Double(3434.34)); 
            tm.put("Tom Smith", new Double(123.22)); 
            tm.put("Jane Baker", new Double(1378.00)); 
            tm.put("Todd Hall", new Double(99.22)); 
            tm.put("Ralph Smith", new Double(-19.08)); 

            ValueComparator<String> vc = new ValueComparator<String>(tm);
            TreeMap<String, Double> sortedTm = 
                    new TreeMap<String, Double>(vc);
            sortedTm.putAll(tm);

            System.out.println(sortedTm.keySet());
            System.out.println(sortedTm.containsKey("John Doe"));
            // The comparator doesn't tolerate null!!!
            System.out.println(!sortedTm.containsKey("Doe"));
        }


}

person alvas    schedule 07.03.2012    source источник


Ответы (1)


Это не ракетостроение ...

Вставьте это вместо закомментированного кода:

if (a == null) {
    return b == null ? 0 : -1;
} else if (b == null) {
    return 1;
} else 

Это рассматривает null как меньшее значение, чем любой ненулевой экземпляр Double.


Ваша версия неверна:

if ((a==null) || (b==null)) {return -1;}

Это говорит: «Если a равно null или b равно null, тогда a меньше, чем b».

Это приводит к фиктивным отношениям, таким как

null < 1.0  AND 1.0 < null

null < null

Подобные вещи приводят к тому, что инварианты дерева ломаются, когда в наборе/карте есть нули, и приводят к непоследовательному и нестабильному порядку ключей ... и хуже.

Требования для действительного compare метода изложены в javadocs. Математическая версия заключается в том, что метод должен определять общий порядок по область всех возможных входных значений.

person Stephen C    schedule 07.03.2012
comment
Ах, да, чтобы сделать его меньше, чем ненулевой!!! Я пробовал if ((a==null) || (b==null)) {return -1;}. Но это не сортирует карту должным образом. Почему это так? - person alvas; 07.03.2012
comment
Потому что это нарушает ограничение, что comparator.compare(x, x) == 0 при x.equals(x), особенно при x == null. - person Louis Wasserman; 07.03.2012