Сортировать LinkedHashMap с LinkedList <Integer>в качестве ключа - PullRequest
1 голос
/ 09 февраля 2020

Я хочу отсортировать LinkedHashMap, который имеет LinkedList<Integer> в качестве ключа и float[] в качестве значения.

Например, скажем, у меня есть такой LinkedHashMap, как это:

LinkedHashMap<LinkedList<Integer>, float[]> hm = new LinkedHashMap<>();
LinkedList<Integer> linkedlist;

linkedlist = new LinkedList<>();
linkedlist.add(10);
linkedlist.add(7);
hm.put(linkedlist, new float[]{0.14f, 1.2f, 85.01f});

linkedlist = new LinkedList<>();
linkedlist.add(0);
linkedlist.add(41);
hm.put(linkedlist, new float[]{10.3f, 50.05f, 9.9f});

linkedlist = new LinkedList<>();
linkedlist.add(210);
linkedlist.add(3);
hm.put(linkedlist, new float[]{17.0f, 4.0f, 2.1f});

Что теперь Я хочу, чтобы выходные данные были:

{0, 41}, {10.3f, 50.05f, 9.9f}

{10, 7}, {0.14f, 1.2 f, 85.01f}

{210, 3}, {17.0f, 4.0f, 2.1f}

Но когда я использую предложенное решение (предложенное некоторыми из вас в раздел комментариев, в котором говорится, что он является дубликатом другого поста, который уже имеет правильный ответ - тот, что ниже, ссылка на него здесь ), где он создал новый LinkedHashMap (потому что я не знаю, как отсортировать оригинальный LinkedHashMap на месте этим кодом, к сожалению) вот так:

LinkedHashMap<LinkedList<Integer>, float[]> sortedMap = new LinkedHashMap<>();
hm.entrySet()
    .stream()
    .sorted(Map.Entry.comparingByKey())
    .forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
hm = sortedMap;

My NetBeans 8.0.2 показывает мне ошибку о строке .sorted(Map.Entry.comparingByKey()) говоря:

incompatible types: inference variable K has incompatible bounds equality constraints: LinkedList<Integer> upper bounds: Comparable <? super K> where K,V are type-variables: K extends Comparable<? super K> declared in method <K,V>comparingByKey() V extends Object declared in method <K,V>comparingByKey()

I подумал, может быть, по какой-то причине значения в LinkedList неверны, поэтому я проверил это так, и это показывает, что все они верны (я проверил только первые 50 записей, так как в списке есть ху их сотни):

for (int i = 0; i < hm.size(); i++) {
    if (i < 50) {
        for (Map.Entry<LinkedList<Integer>, float[]> entry : hm.entrySet()) {
            LinkedList<Integer> k = entry.getKey();
            System.out.println(k);
        }
    }
}

Ответы [ 2 ]

1 голос
/ 09 февраля 2020

Простое исправление: вы сказали, что хотите отсортировать по первому (0-му) элементу списка. Поэтому укажите, что:

    hm.entrySet()
        .stream()
        .sorted(Comparator.comparing(me -> me.getKey().get(0)))
        .forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));

С помощью этой сортировки давайте попробуем выписать отсортированную карту впоследствии, например:

    sortedMap.forEach((k, v) -> System.out.println("" + k + " -> " + Arrays.toString(v)));
[0, 41] -> [10.3, 50.05, 9.9]
[10, 7] -> [0.14, 1.2, 85.01]
[210, 3] -> [17.0, 4.0, 2.1]

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

    hm.entrySet()
        .stream()
        .sorted(Comparator.comparing(me -> me.getKey().get(0)))
        .forEachOrdered(x -> {
            hm.remove(x.getKey());
            hm.put(x.getKey(), x.getValue());
        });

    hm.forEach((k, v) -> System.out.println("" + k + " -> " + Arrays.toString(v)));

Теперь вывод такой же, как и выше.

1 голос
/ 09 февраля 2020

Проблема с этим подходом состоит в том, что ключ, который у вас есть, LinekdList<Integer> не Comparable. Вы можете преодолеть это, предоставив пользовательский Comparator.

. Обычный способ реализации таких компараторов - сравнивать целые числа в совпадающих местах, пока вы не встретите пару, которая не равна , Если один из списков короче другого, и вы не указали в нем несоответствующий элемент до его окончания, вы можете определить его как «меньший», чем длинный список:

Comparator<LinkedList<Integer>> cmp = new Comparator<LinkedList<Integer>>() {
    @Override
    public int compare(LinkedList<Integer> o1, LinkedList<Integer> o2) {
        Iterator<Integer> i1 = o1.iterator();
        Iterator<Integer> i2 = o2.iterator();

        // Iterate over the first list
        while (i1.hasNext()) {
            Integer x1 = i1.next();

            // If the second list has no more elements, it's "smaller"
            if (!i2.hasNext()) {
                return 1;
            }

            Integer x2 = i2.next();
            int cmp = Integer.compare(x1, x2);
            if (cmp != 0) {
                // If the matching items aren't equal, we know which list is "smaller"
                return cmp;
            }
        }

        // Done going over the first list.
        // If the second one still has items, it's "bigger"
        if (i2.hasNext()) {
            return -1;
        }

        // If not, both lists are equal
        return 0;
    }
};

Один раз у вас есть этот компаратор, вам просто нужно использовать его для сортировки ключей карты:

LinkedHashMap<LinkedList<Integer>, float[]> sortedMap = new LinkedHashMap<>();
hm.entrySet()
        .stream()
        .sorted(Map.Entry.comparingByKey(cmp)) // Here
        .forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
hm = sortedMap;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...