Как написать собственный компаратор для TreeMap в Java? - PullRequest
0 голосов
/ 04 февраля 2019

Я хочу сохранить пары ключ-значение в TreeMap и отсортировать записи на основе значения Key согласно следующей логике:

Сортировать по длине ключа.Если длина двух ключей одинакова, сортируйте их по алфавиту.Например, для следующих пар ключ-значение.

IBARAKI MitoCity
TOCHIGI UtunomiyaCity
GUNMA MaehashiCity
SAITAMA SaitamaCity
CHIBA ChibaCity
TOKYO Sinjyuku
KANAGAWA YokohamaCity

Ожидаемый результат выглядит следующим образом.

CHIBA : ChibaCity
GUNMA : MaehashiCity
TOKYO : Sinjyuku
IBARAKI : MitoCity
SAITAMA : SaitamaCity
TOCHIGI : UtunomiyaCity
KANAGAWA : YokohamaCity

Ответы [ 6 ]

0 голосов
/ 05 февраля 2019

Вы можете определить Comparator<String>, который вам нужен в вызове конструктора для TreeMap:

import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;


public class Main {
    static final Map<String, String> map = 
            new TreeMap<String, String> (new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            int diff_length = o1.length() - o2.length();
            if (diff_length != 0) return diff_length;
            return o1.compareTo(o2);
        }
    });

    public static final void main(String[] args) {
        map.put("IBARAKI", "MitoCity");
        map.put("TOCHIGI", "UtunomiyaCity");
        map.put("GUNMA", "MaehashiCity");
        map.put("SAITAMA", "SaitamaCity");
        map.put("CHIBA", "ChibaCity");
        map.put("TOKYO", "Sinjyuku");
        map.put("KANAGAWA", "YokohamaCity");

        System.out.println(map);
    }

}
0 голосов
/ 04 февраля 2019

Вместо прямого преобразования Map в TreeMap вы можете использовать этот метод

 public static Map toTreeMap(Map hashMap) 
    { 
        // Create a new TreeMap 
        Map treeMap = new TreeMap<>(new Comparator<Map.Entry<String, String>>(){

          public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2 ) 
       {
             if (o1.getKey().length() > o2.getKey().length()) {
                      return 1;
                }
            if (o1.getKey().length() > o2.getKey().length()) {
                      return -1;
               }
           return o1.getKey().compareTo(o2.getKey());
      }

      }); 

     for(Map.entry e : hashmap){
        treeMap.put(e.getKey(),e.getValue);
     }


        return treeMap; 

}

0 голосов
/ 04 февраля 2019

Это можно сделать следующим образом.

  public static void main(String[] args) {

      Map<String, String> map = new TreeMap<>(new CustomSortComparator());

      map.put("IBARAKI", "MitoCity");
      map.put("TOCHIGI", "UtunomiyaCity");
      map.put("GUNMA", "MaehashiCity");
      map.put("SAITAMA", "SaitamaCity");
      map.put("CHIBA", "ChibaCity");
      map.put("TOKYO", "Sinjyuku");
      map.put("KANAGAWA", "YokohamaCity");

      System.out.println(map);

  }

Параметр CustomSortComparator был определен следующим образом.

public class CustomSortComparator implements Comparator<String> {

  @Override
  public int compare(String o1, String o2) {
    if (o1.length() > o2.length()) {
      return 1;
    }
    if (o1.length() < o2.length()) {
      return -1;
    }
    return returnCompareBytes(o1, o2);
  }

  private int returnCompareBytes(String key1, String key2) {
    for (int i = 0; i < key1.length() - 1; i++) {
      if (key1.charAt(i) > key2.charAt(i)) {
        return 1;
      }
      if (key1.charAt(i) < key2.charAt(i)) {
        return -1;
      }
    }
    return 0;
  }
}

0 голосов
/ 04 февраля 2019

Вам необходимо создать уникальный компаратор для сравнения ключей карты.Но поскольку вы также хотите напечатать значения, вам следует сравнить все наборы записей:

Comparator<Map.Entry<String, String>> c = new Comparator<Map.Entry<String, String>>() {
  @Override
  public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
    int q = Integer.compare(o1.getKey().length(), o2.getKey().length());
    return q != 0 ? q : o1.getKey().compareTo(o2.getKey());
  }
};

Затем вы можете использовать этот компаратор для сортировки:

map.entrySet().stream().sorted(c).forEach(System.out::println);
0 голосов
/ 04 февраля 2019

Вы можете передать Компаратор как параметр конструктору Карты.Согласно документации, он используется только для ключей:

/**
 * Constructs a new, empty tree map, ordered according to the given
 * comparator.  All keys inserted into the map must be <em>mutually
 * comparable</em> by the given comparator: {@code comparator.compare(k1,
 * k2)} must not throw a {@code ClassCastException} for any keys
 * {@code k1} and {@code k2} in the map.  If the user attempts to put
 * a key into the map that violates this constraint, the {@code put(Object
 * key, Object value)} call will throw a
 * {@code ClassCastException}.
 *
 * @param comparator the comparator that will be used to order this map.
 *        If {@code null}, the {@linkplain Comparable natural
 *        ordering} of the keys will be used.
 */
public TreeMap(Comparator<? super K> comparator) {
    this.comparator = comparator;
}

Таким образом, вы можете передать компаратор по длине ключа следующим образом:

new TreeMap<>(Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()))
0 голосов
/ 04 февраля 2019

Для этого вам нужно написать собственный comparator и использовать его в TreeMap, например:

public class StringComparator implements Comparator<String> {

    @Override
    public int compare(String s1, String s2) {
        return s1.length() == s2.length() ? s1.compareTo(s2) : s1.length() - s2.length();
    }

    public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
        Map<String, String> map = new TreeMap<>(new StringComparator());
        map.put("IBARAKI", "MitoCity");
        map.put("TOCHIGI", "UtunomiyaCity");
        map.put("GUNMA", "MaehashiCity");
        map.put("SAITAMA", "SaitamaCity");
        map.put("CHIBA", "ChibaCity");
        map.put("TOKYO", "Sinjyuku");
        map.put("KANAGAWA", "YokohamaCity");

        System.out.println(map);
    }

}

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

...