简体   繁体   中英

How to sort a Map in Java by its key but if the Key is combination of (String + numeric)

I have created a map called result.

In the sortByKeys method as my keys are String with Numeric values, I have converted them to Integer key type Map then sorted them.

Map<String, String> unsortMap = new TreeMap<String, String>();
unsortMap.put("room~1", "e");
unsortMap.put("room~2", "y");
unsortMap.put("room~10", "n");
unsortMap.put("room~4", "j");
unsortMap.put("room~5", "m");
unsortMap.put("room~3", "f");

Set set2 = unsortMap.entrySet();
Iterator iterator2 = set2.iterator();

while (iterator2.hasNext()) {
     /* Iterate */
    Map.Entry me2 = (Map.Entry) iterator2.next();
    String key = (String) me2.getKey();
    Object value = (Object) me2.getValue();
    System.out.println("Key ==>" + key + " Value ==>" + value);
}

# Current Output:#
/* current result */
Key ==>room~1 Value ==>e 
Key ==>room~10 Value ==>n
Key ==>room~2 Value ==>y
Key ==>room~3 Value ==>f
Key ==>room~4 Value ==>j
Key ==>room~5 Value ==>m

#Expected O/p:#
/* required result */
Key ==>room~1 Value ==>e
Key ==>room~2 Value ==>y
Key ==>room~3 Value ==>f
Key ==>room~4 Value ==>j
Key ==>room~5 Value ==>m
Key ==>room~10 Value ==>n 

Create a custom key object

public class Key implements Comparable<Key>{
    String name;
    int id;

    public Key(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public int compareTo(Key o) {
        if(Objects.equals(name, o.name)){
            return Integer.compare(id, o.id);
        }else{
            return name.compareTo(o.name);
        }
    }

    @Override
    public String toString() {
        return name +"~"+ id;
    }

    @Override
    public boolean equals(Object o){
    ...
    @Override
    public int hashCode(){
    ...
}

and use it like this:

    Map<Key, String> unsortMap = new TreeMap<>();
    unsortMap.put(new Key("room", 5), "e");

But if the String is always room you should use it in the key

Without changing your code you can do like this.Need to write your own custom comparator.please always keep in mind that you can always create comparator login when you need sorting as per your own way

Map<String, String> unsortMap = new TreeMap<String, String>(new Comparator<String>() {

            @Override
            public int compare(String o1, String o2) {
                // TODO Auto-generated method stub

                int j=Integer.parseInt(o1.substring(o1.indexOf("~")+1));
                int k=Integer.parseInt(o2.substring(o1.indexOf("~")+1));
                return j-k;
            }

        });

unsortMap.put("room~1", "e");
unsortMap.put("room~2", "y");
unsortMap.put("room~10", "n");
unsortMap.put("room~4", "j");
unsortMap.put("room~5", "m");
unsortMap.put("room~3", "f");

Set set2 = unsortMap.entrySet();
Iterator iterator2 = set2.iterator();

while (iterator2.hasNext()) {
     /* Iterate */
    Map.Entry me2 = (Map.Entry) iterator2.next();
    String key = (String) me2.getKey();
    Object value = (Object) me2.getValue();
    System.out.println("Key ==>" + key + " Value ==>" + value);
}

using stream and LinkedHashMap to maintain order

    Map<String, String> unsortMap = new TreeMap<String, String>();
    unsortMap.put("room~1", "e");
    unsortMap.put("room~2", "y");
    unsortMap.put("room~10", "n");
    unsortMap.put("room~4", "j");
    unsortMap.put("room~5", "m");
    unsortMap.put("room~3", "f");
    Comparator<String> c = (s1, s2) -> Integer.parseInt(s1.split("~")[1])   - Integer.parseInt(s2.split("~")[1]);
    Map<String, String> sortedMap = unsortMap.keySet()
            .stream()
            .sorted(c)
            .collect(Collectors.toMap(k -> k, k -> unsortMap.get(k), (k, v) -> v, LinkedHashMap::new));
    System.out.println(sortedMap);

Output

{room~1=e, room~2=y, room~3=f, room~4=j, room~5=m, room~10=n}

A more generic comparator for keys of type String that contains digits and letters:

Map<String, Double> result = new TreeMap<String, Double>(new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            String numericPart1 = o1.replaceAll("\\D+","");
            String numericPart2 = o2.replaceAll("\\D+","");
            String alphaPart1 = o1.replace(numericPart1, "");
            String alphaPart2 = o2.replace(numericPart2, "");

            if(alphaPart1.equals(alphaPart2)) {
                return Integer.compare(Integer.parseInt(numericPart1), Integer.parseInt(numericPart2));
            } else {
                return alphaPart1.compareTo(alphaPart2);
            }
        }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM