Charles
Charles

Reputation: 33

Sort Nested HashMap By Inner Value

I am trying to sort a nested HashMap, HashMap<Integer, HashMap<Integer, String>> myMap = new HashMap<>(), by a specific value in the inner HashMap. The program reads a delimited file that contains the following values:

000001014|A||Harvey|T|Dent|05/27/1991|0902|000001014|05/27/1991|01/01/3000| 000001388|A||Tony|K|Stark|09/19/1992|0054|000001388|09/19/1992|01/01/3000| 000001395|A||Steve|C|Rogers|10/26/1992|7402|000001395|10/26/1992|01/01/3000| 000001396|A||Peter|P|Parker|11/02/1992|1002|000001396|11/02/1992|01/01/3000| 000011148|I||Drax|T|Destroyer|02/17/1992|7005|000011148|02/17/1992|01/01/3000| 000011141|A||Rocket|M|Raccoon|02/10/1992|7170|000011141|02/10/1992|01/01/3000|000001404|A||Natasha||Romanoff|12/28/1992|7240|00001404|12/28/1992|01/01/3000| 000001442|A||Bruce|T|Banner|10/06/1993|7012|000001442|10/06/1993|01/01/3000| 000001450|A||Scott|L|Lang|11/29/1993|0002|000001450|11/29/1993|01/01/3000| 000001486|A||Thor|J|Odinson|07/04/1994|0002|000001486|07/04/1994|01/01/3000|

I chose a Nested HashMap so that each line in the file has its own key and then each element in each line has a key. For example myMap.get(0).get(7) returns 0902, myMap.get(1).get(7) returns 0054, myMap.get(2).get(7) returns 7402. But the problem is that sorting the HashMap by the nested HashMap value has been a real humdinger. So, what I am trying to accomplish is to sort the whole HashMap by the 7th element in the inner map.

Should I sort myMap the old fashion way using a nested loops and binary sort or insertion sort? How do I tackle this problem?

private static Path directory() {
    File home = FileSystemView.getFileSystemView().getHomeDirectory();
    String path = home.getAbsolutePath();
    Path dir;
    //For reference Directory 
    C:\Users\PC_USER_NAME\Desktop\Work\Person\Employees.txt
    if(getProperty("os.name").startsWith("Windows")) {//specify your 
        directory Windows
        dir = Paths.get(path + File.separator + "Work" + File.separator + "Person");
    } else {//Specify your directory Mac
        dir = Paths.get(File.separator + "Users" + File.separator + 
        getProperty("user.name") + File.separator + "Desktop" + File.separator + "Work" + File.separator + "Person");
    }
    return dir;
}

private static void readFile() {
    HashMap<Integer, HashMap<Integer, String>> myMap = new HashMap<>();
    HashMap<Integer, String> inner = new HashMap<>();
    BufferedReader reader;
    String line;
    int count = 0;
    try {
        File dir = new File(directory().toString());
        File[] files = dir.listFiles((File pathname) -> 
        pathname.getName().startsWith("Employees"));
        File lastModifiedFile = files[0];

        for (File file : files) {
            if (lastModifiedFile.lastModified() < file.lastModified()) {
                lastModifiedFile = file;
            }
        }

        reader = new BufferedReader(new FileReader(lastModifiedFile));
        //Skips the header.
        reader.readLine();
        while((line = reader.readLine()) != null) {
            String[] keyValue = line.split("\\|");

            for (int i = 0; i < keyValue.length; i++) {
                inner.put(i, keyValue[i]);
            }
            myMap.put(count, inner);
            count++;
            inner = new HashMap<>();
        }
        reader.close();
    } catch (IOException e) { e.printStackTrace(); }
    sort(myMap);
}

private static void sort(HashMap<Integer, HashMap<Integer, String>> myMap) {
    Set<Entry<Integer, HashMap<Integer, String>>> sorted = 
    myMap.entrySet();

    for(Entry<Integer, HashMap<Integer, String>> entry : sorted) {
        System.out.println(entry.getKey() + " ==> " +   entry.getValue().get(7));
    }
    //Won't add this method code for brevity sake   
    writeFile();
}

Upvotes: 0

Views: 44

Answers (1)

m.antkowicz
m.antkowicz

Reputation: 13581

First of all - what does it mean to sort a HashMap? To print sorted values as I guess what does mean you won't be sorting Map itself, but some kind of collection of it's values

Second thing - why do you want to keep such data in a Map? It sounds like really bad idea, and you just spotted the first argument why

For me you should create some kind of Row class like

public class Row {
    private List<String> items; // for '|' splitted values in a row, maybe it should be even String[]?

    ...
}

and keep your whole file as a List<Row>. Then you can create your own Comparator or even make Row implements Comparable

public class Row implements Comparable<Row>{
    private List<String> items = new ArrayList<>();

    ...

    @Override
    public int compareTo(Row that) {
        return this.items.get(8).compareTo(that.items.get(7));
    }
}

Now you can easily sort the file using Collections.sort() util

Please notice that implementing Comparator allow you to create many versions of them (like SortBy6thComparator, SortBy7thComparator, SortBy8thComparator...). You just need to use then another version of sort method:

public static <T> void sort(List<T> list, Comparator<? super T> c)

Upvotes: 1

Related Questions