Skip to content

How to sort the keySet() of a TreeMap with keys containing number?

I’ll briefly describe what I did and then show how the result I got, differs from my desired result.

Thanks in advance for any suggestions.

Java code was created in a java online compiler and is executable there without error message in any case.

Java online compiler, which was used

Short description:

I want to assign a boolean value to every possible combination between row index and column index of a square matrix.
Only the main diagonal is to be excluded from this. For this I use a TreeMap <String, Boolean>

I form the keys of the TreeMap by linking {row index + “-“+column index} in a for loop.
At the beginning, all values of the keys are assigned {false}.

In a second loop, every possible combination of a chosen index basicL with other indices (=keys) is to be linked with the Boolean value true (again without values of the main diagonals). As a result, TreeMap.keySet() is to be printed in sorted order (sorted by the keys). Example is for basicL = 4;

Illustration of the matrix (Boolean true=green, Boolean false=white, excluded=grey):

enter image description here

Java-Code:

import java.util.TreeMap;

public class Main {

  static TreeMap<String, Boolean> booleanMap = new TreeMap<>();

  public static void main(String[] args) {

    //all values of symmetric matrix without diagonal axis

    int max = 16;
    int basicL = 4;

    for (int i = 1; i <= max; i++) {

      for (int j = 1; j <= max; j++) {

        if (j != i) {
          booleanMap.put(i + "-" + j, Boolean.valueOf(false));
        }
      }
    }

    System.out.println("-----------------------------------------------------");
    System.out.println("TreeMap has size:  " + booleanMap.size());
    System.out.println("TreeMap values:    " + booleanMap.values());
    System.out.println("TreeMap keySet:   " + booleanMap.keySet());
    System.out.println("-----------------------------------------------------");

    // setting true-conditions

    for (int i = 1; i <= max; i++) {

      if (i != basicL) {

        for (int j = 1; j <= max; j++) {

          if (j == basicL) {

            booleanMap.replace(i + "-" + j, Boolean.valueOf(true));
          }
        }
      }

      if (i == basicL) {

        for (int j = 1; j <= max; j++) {

          if (j != i) {

            booleanMap.replace(i + "-" + j, Boolean.valueOf(true));

          }
        }
      }
    }

    System.out.println("TreeMap values after looping:    " + booleanMap.values());
    System.out.println("TreeMap keySet after looping:    " + booleanMap.keySet());
    System.out.println("-----------------------------------------------------");
  }
}

Result achieved for booleanMap.keySet();

[1-10, 1-11, 1-12, 1-13, 1-14, 1-15, 1-16, 1-2, 1-3, 1-4, 1-5, 1-6, 1-7, 1-8, 1-9, 10-1, 10-11, 10-12, 10-13, 10-14, 10-15, 10-16, 10-2 .... ]

Desired Result:

[1-2, 1-3, 1-4, 1-5, 1-6, 1-7, 1-8, 1-9, 1-10, 1-11, 1-12, 1-13, 1-14, 1-15, 1-16, 2-1, 2-3, 2-4, 2-5, 2-6, 2-7, 2-8, 2-9, 2-10, 2-11, 2-12 .... ]

Answer

The indexes are sorted lexicographical and not according to the value of the number. A solution would be to prepend zeros (1-12 -> 001-012). Another would be to pass a custom comparator to the constructor of TreeMap as shown in the answer by @samabcde.

I suggest that you create a custom class for the position in the matrix. You can implement compareTo which lets the TreeMap handle the sorting automatically for you. Additionally, you can simplify the second loop significantly and remove the boxing of the booleans.

TreeMap<Position, Boolean> booleanMap = new TreeMap<>();

int max = 16;
int basicL = 4;

for (int i = 1; i <= max; i++) {
    for (int j = 1; j <= max; j++) {
        if (j != i) {
            booleanMap.put(new Position(i, j), Boolean.FALSE);
        }
    }
}
for (int i = 1; i <= max; i++) {
    for (int j = 1; j <= max; j++) {
        if ((i != basicL && j == basicL) || (i == basicL && j != i)) {
            booleanMap.replace(new Position(i, j), Boolean.TRUE);
        }
    }
}
static class Position implements Comparable<Position> {

    private final int x;
    private final int y;

    public Position(final int x, final int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public int compareTo(final Position o) {
        final int res = Integer.compare(getX(), o.getX());
        return (res != 0) ? res : Integer.compare(getY(), o.getY());
    }

    @Override
    public String toString() {
        return x + "-" + y;
    }
}