Как правильно изменить порядок вложенных java карт - PullRequest
0 голосов
/ 05 мая 2020

Я пытаюсь изменить порядок вложенной карты.

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

Вот структура карты Map<String, HashMap<String, Object>> playersDataMap = new HashMap<> ();

И это пара методов, которые я скопировал с веб-сайта, но ни один из них не сработал. Он всегда возвращает мне товар в том же порядке.

    public static <K extends Comparable, V> Map<K,V> sortByKeys(Map<K,V> map)
    {
        Map<K, V> treeMap = new TreeMap<>(new Comparator<K>() {
            @Override
            public int compare(K a, K b) {
                return b.compareTo(a);
            }
        });

        treeMap.putAll(map);

        return treeMap;
    }

    public static <K, V> Map<K,V> sortByTreeMap(Map<K,V> unsortedMap)
    {
        // construct a TreeMap from given Map and return a reverse order
        // view of the mappings contained in this map
        return new TreeMap<>(unsortedMap).descendingMap();
    }

Я также пробовал изменить HashMap на LinkedHashMap, но безуспешно, те же результаты.

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

Вот пример того, что я пытаюсь реализовать

Map<String, HashMap<String, Object>> playersDataMap = new LinkedHashMap<> ();
for (int i = 1; i < 40; i++)
{
    HashMap<String, Object> playerMap = new HashMap<> ();
    playerMap.put ("name", "abc"+i);
    playerMap.put ("pointsScored", i * 10);
    playersDataMap.put ("x"+i, playerMap);
}


Map<String, HashMap<String, Object>> inversedPlayerDataMap = new LinkedHashMap<>();
inversedPlayerDataMap = new TreeMap<>(Comparator.reverseOrder());
inversedPlayerDataMap.putAll(playersDataMap);

for (Map.Entry<String, HashMap<String, Object>> player : inversedPlayerDataMap.entrySet ())
{
    System.out.printf ("Debug: player key: %s playerValueScore: %s \n", player.getKey (), player.getValue ().get("pointsScored"));
}

Результаты: «Отладка: ключ игрока: x9 pointsScored: 90» «Debug: player key: x390 pointsScored: 390 "" Отладка: ключ игрока: x30 очков Набрано: 30 "...

Ожидаемый результат:" Отладка: ключ игрока: x390 очков Набрано: 390 "" Отладка: ключ игрока: x380 очков Набрано: 380 "...

Ответы [ 3 ]

3 голосов
/ 05 мая 2020

Если все, что вы хотите сделать, это перевернуть текущую карту, это сделает это.

Вот тестовая карта


for (int i = 10; i < 300; i += 10) {

    playerMap = new HashMap<String, Object>();
    playerMap.put("name", "person" + (i / 10));
    playerMap.put("pointsScored", i);

    playersDataMap.put("x" + i, playerMap);

}

Вот компаратор. Обратите внимание, что это зависит от того, что x является одинаковым для ключей на прилагаемой карте.

Comparator<String> comp = Comparator
        .comparing(String::length)
        .thenComparing(String::compareTo)
        .reversed();

И сортировка

inversedPlayerDataMap = new TreeMap<>(comp);
inversedPlayerDataMap.putAll(playersDataMap);


for (Map.Entry<String, HashMap<String, Object>> player : inversedPlayerDataMap
                .entrySet()) {
    System.out.printf(
                    "Debug: player key: %s playerValueScore: %s \n",
                    player.getKey(),
                    player.getValue().get("pointsScored"));
    }
}

Выводит

...
...
...
Debug: player key: x130 playerValueScore: 130 
Debug: player key: x120 playerValueScore: 120 
Debug: player key: x110 playerValueScore: 110 
Debug: player key: x100 playerValueScore: 100 
Debug: player key: x90 playerValueScore: 90 
Debug: player key: x80 playerValueScore: 80 
...
...
...

Не Вы уверены, почему вы используете карту карт. Имеет ли значение ключ к externalMap (возможно, как назначенное лицо команды?)

0 голосов
/ 08 мая 2020

Оба приведенных выше ответа работали, но в некоторой степени. Они не работали со смешанной строкой.

Итак, я сделал замену HashMap на connectedHashMap. Затем я добавил keySet этой карты во вновь созданный список строк и отменил его с помощью Collections.reverse, затем повторил этот список и добавил зарезервированный порядок в новую карту.

Вот код моей функции инвертирования .

Важно , аргумент, который я передал как playerDataMap, - это connectedHashMap. Для получения дополнительных сведений о LinkedHashMap go перейдите по следующей ссылке https://beginnersbook.com/2013/12/linkedhashmap-in-java/. спасибо!

public static Map<String, HashMap<String, Object>> invertMapUsingList (Map<String, HashMap<String, Object>> playersDataMap)
{
        Map<String, HashMap<String, Object>> inversedPlayerDataMap = new LinkedHashMap<> ();
        List<String> reverseOrderedKeys = new ArrayList<String>(playersDataMap.keySet());
        Collections.reverse(reverseOrderedKeys);
        for (String key : reverseOrderedKeys)
        {
            inversedPlayerDataMap.put (key, playersDataMap.get(key));
        }

        return inversedPlayerDataMap;
}
0 голосов
/ 05 мая 2020

[Исходный ответ]

Ваш подход к использованию Map может быть проблематичным c. Вы должны создать новый тип и использовать List нового типа.

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class MyType {
    String playerKey;
    Map<String, Object> map = new HashMap<String, Object>();

    public MyType(String id, Map<String, Object> map) {
        this.playerKey = id;
        this.map = map;
    }

    public String getPlayerKey() {
        return playerKey;
    }

    @Override
    public String toString() {
        return "playerKey=" + playerKey + ", pointsScored=" + map.get("pointsScored");
    }
}

public class Main {
    public static void main(String[] args) {
        List<MyType> playersData = new ArrayList<MyType>();
        playersData.add(new MyType("x1", Map.of("name", "john", "pointsScored", 50)));
        playersData.add(new MyType("x11", Map.of("name", "harry", "pointsScored", 55)));
        playersData.add(new MyType("x2", Map.of("name", "tina", "pointsScored", 60)));
        playersData.add(new MyType("y1", Map.of("name", "richard", "pointsScored", 60)));
        playersData.add(new MyType("y12", Map.of("name", "kim", "pointsScored", 45)));
        playersData.add(new MyType("y3", Map.of("name", "karen", "pointsScored", 65)));
        System.out.println("Orinally:");
        playersData.stream().forEach(System.out::println);
        playersData.sort(new Comparator<MyType>() {
            @Override
            public int compare(MyType t1, MyType t2) {
                String s1 = t1.getPlayerKey();
                String s2 = t2.getPlayerKey();

                int compVal;
                int n1 = 0, n2 = 0;
                String sn1 = "", sn2 = "";

                // Pattern to find a sequence of digits
                Pattern pattern = Pattern.compile("\\d+");
                Matcher matcher;

                matcher = pattern.matcher(s1);
                if (matcher.find()) {
                    // Number from first string
                    sn1 = matcher.group();
                    n1 = Integer.valueOf(sn1);
                }

                matcher = pattern.matcher(s2);
                if (matcher.find()) {
                    // Number from first string
                    sn2 = matcher.group();
                    n2 = Integer.valueOf(sn2);
                }

                // Compare the string part
                compVal = s2.substring(0, s2.indexOf(sn2)).compareTo(s1.substring(0, s1.indexOf(sn1)));

                // If string parts are same, compare the number parts
                if (compVal == 0 && n1 != 0 && n2 != 0) {
                    compVal = Integer.compare(n2, n1);
                }
                return compVal;
            }
        });

        System.out.println("\nSorted in reversed order of playerKey:");
        playersData.stream().forEach(System.out::println);
    }
}

[Обновить]

Вы можете использовать Map следующим образом:

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 
 * Comparator to compare alphanumeric words in the form of LETTERS+DIGITs e.g.
 * A1, ABC123 etc.
 *
 */
class MyComparator implements Comparator<String> {

    @Override
    public int compare(String s1, String s2) {

        int compVal;
        int n1 = 0, n2 = 0;
        String sn1 = "", sn2 = "";

        // Pattern to find a sequence of digits
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher;

        matcher = pattern.matcher(s1);
        if (matcher.find()) {
            // Number from first string
            sn1 = matcher.group();
            n1 = Integer.valueOf(sn1);
        }

        matcher = pattern.matcher(s2);
        if (matcher.find()) {
            // Number from first string
            sn2 = matcher.group();
            n2 = Integer.valueOf(sn2);
        }

        // Compare the string part
        compVal = s2.substring(0, s2.indexOf(sn2)).compareTo(s1.substring(0, s1.indexOf(sn1)));

        // If string parts are same, compare the number parts
        if (compVal == 0 && n1 != 0 && n2 != 0) {
            compVal = Integer.compare(n2, n1);
        }
        return compVal;
    }
}

public class Main {
    public static void main(String[] args) {
        Map<String, HashMap<String, Object>> playersDataMap = new HashMap<>();
        for (int i = 1; i <= 10; i++) {
            HashMap<String, Object> playerMap = new HashMap<>();
            playerMap.put("name", "abc" + i);
            playerMap.put("pointsScored", i * 10);
            playersDataMap.put("x" + i, playerMap);
        }

        Map<String, HashMap<String, Object>> inversedPlayerDataMap = new TreeMap<>(new MyComparator());
        inversedPlayerDataMap.putAll(playersDataMap);
        for (Map.Entry<String, HashMap<String, Object>> entry : inversedPlayerDataMap.entrySet()) {
            System.out
                    .println("playerKey=" + entry.getKey() + ", pointsScored=" + entry.getValue().get("pointsScored"));
        }
    }
}

Вывод:

playerKey=x10, pointsScored=100
playerKey=x9, pointsScored=90
playerKey=x8, pointsScored=80
playerKey=x7, pointsScored=70
playerKey=x6, pointsScored=60
playerKey=x5, pointsScored=50
playerKey=x4, pointsScored=40
playerKey=x3, pointsScored=30
playerKey=x2, pointsScored=20
playerKey=x1, pointsScored=10
...