Сделать компаратор TreeMap терпеть ноль - PullRequest
4 голосов
/ 07 марта 2012

Этот настраиваемый Valuecomparator сортирует 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"));
        }


}

1 Ответ

6 голосов
/ 07 марта 2012

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

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

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

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


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

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

Здесь написано, что "если а равно нулю или b равно нулю, то а меньше, чем b".

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

null < 1.0  AND 1.0 < null

null < null

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

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

...