Сортировать HashMap по значению и конвертировать в новую карту - PullRequest
1 голос
/ 10 мая 2019

Я пытаюсь преобразовать Map<String, Map<String, String>> в LinkedHashMap<String, Double> при сортировке по определенному внутреннему value.Моя борьба не столько с сортировкой, сколько с преобразованием в процессе.

Учитывая этих потомков Map и одного родителя Map:

Map<String, String> man = new HashMap<>();
man.put("h_ratio", "0.45");
man.put("w_ratio", "0.75");
man.put("a_ratio", "0.19");

Map<String, String> bear = new HashMap<>();
bear.put("h_ratio", "0.23");
bear.put("w_ratio", "0.72");
bear.put("a_ratio", "0.95");

Map<String, String> pig = new HashMap<>();
pig.put("h_ratio", "0.37");
pig.put("w_ratio", "0.64");
pig.put("a_ratio", "0.81");

Map<String, Map<String, String>> unsortedOrganisms = new HashMap<>();
unsortedOrganisms.put("man", man);
unsortedOrganisms.put("bear", bear);
unsortedOrganisms.put("pig", pig);

Как мне эффективносоздать LinkedHashMap<String, Double> сортировку по a_ratio так, чтобы в результате получилось:

{bear={0.95}, pig={0.81}, man={0.19}}

Реальный размер unsortedOrganisms равен 50 000, а реальный размер каждого внутреннего Map50.

Исследования показывают, наиболее эффективный способ, вероятно,

Создание List набора Entry на карте и сортировка List с использованием Collections.sort()

Однако в этом примере предполагается, что выходные данные Map имеют ту же структуру, что и входная карта.Тогда как мой результат требует преобразования в LinkedHashMap типа <String, Boolean>

Ответы [ 3 ]

1 голос
/ 10 мая 2019

Это проще всего с потоками:

input.entrySet().stream()
    // Get just the (key, a_ratio) pair
    .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), e.getValue().get("a_ratio"))
    // Sort the entries by value, descending.
    .sorted(Map.Entry.comparingByValue().reversed())
    .collect(toList());

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

1 голос
/ 10 мая 2019

Oldschool версия без потоков:

  public static LinkedHashMap<String, Double> sortOrganisms(Map<String, Map<String, String>> data, String key){

    ArrayList<AbstractMap.SimpleEntry<String, Double> > organisms = new ArrayList<>(data.size());

    for (String name : data.keySet()) {
      Double value = Double.parseDouble(data.get(name).get(key));
      organisms.add(new AbstractMap.SimpleEntry<>(name, value));
    }

    organisms.sort(new Comparator<AbstractMap.SimpleEntry<String, Double> >() {
      @Override
      public int compare(AbstractMap.SimpleEntry<String, Double> o1, AbstractMap.SimpleEntry<String, Double> o2) {
        // reverse sorting by value
        return -Double.compare(o1.getValue(),o2.getValue());
      }
    });

    LinkedHashMap<String, Double> result = new LinkedHashMap<>();
    for (AbstractMap.SimpleEntry<String, Double> o : organisms) {
      result.put(o.getKey(), o.getValue());
    }

    return result;

  }
1 голос
/ 10 мая 2019

Вы можете использовать Java Streams для решения этой проблемы:

LinkedHashMap<String, Double> result = unsortedOrganisms.entrySet().stream()
        .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), Double.valueOf(e.getValue().get("a_ratio"))))
        .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (d1, d2) -> d2, LinkedHashMap::new));

Результат будет таким:

{bear=0.95, pig=0.81, man=0.19}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...