user3885256
user3885256

Reputation:

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 

Upvotes: 1

Views: 1379

Answers (4)

Panagiotis Theocharis
Panagiotis Theocharis

Reputation: 11

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);
            }
        }
    });

Upvotes: 0

Jekin Kalariya
Jekin Kalariya

Reputation: 3507

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);
}

Upvotes: 4

Saravana
Saravana

Reputation: 12817

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}

Upvotes: 0

Liviu Stirb
Liviu Stirb

Reputation: 6075

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

Upvotes: 4

Related Questions