Search code examples
javalistcollectionshashmaptreemap

When should I sort Map elements in Java?


I have an excel file that keeps user role and permission as shown below (some fields are omitted for brevity):

User Role | Permission Uuid    
----------|----------------                     
0         | a465433f... 
0         | 43db5a33...
1         | 610e9040... 
0         | 94e85bef... 
1         | 34e85f32...

I am reading an excel file row by row and need to pass a request as shown below to create imported data:

public class PermissionRequest {
    private UserRole userRole;
    private List<UUID> permissionUuidList;
}

I think that I need to map each Permission Uuid by User Role and for this reason I tried to use Map<Integer, List<UUID>> as shown below:

Map<Integer, List<UUID>> userRolePermissionMap = new HashMap<>();
userRolePermissionMap.put(Integer.parseInt(cellList.get(USER_ROLE)),
    Collections.singletonList(UUID.fromString(cellList.get(PERMISSON_UUID))));

But I think it it not correct. So, as the User Role is not sorted in the excel file, should I need a sort or grouping by User Role and then send PermissionRequest to the repository in a loop for create operation? Or should I use a TreeMap for this purpose? If so, how can I use?


Solution

  • HashMap does not guarantee the sorted order, TreeMap is sorted by keys (UserRole in this case) and additionally, the lists of UUIDs can be sorted (if necessary).

    However, the code above uses Collections.singletonList which is not correct because such list is immutable and can contain only one UUID.

    A concise implementation using Java Stream API Collectors.groupingBy with Supplier<Map> and Collectors.mapping may look as follows assuming that there is a list of cellList objects representing rows:

    Map<Integer, List<UUID>> userRolePermissionMap =
            rowsList.stream() // Stream<Row> 
                    .collect(Collectors.groupingBy(
                        cellList -> Integer.parseInt(cellList.get(USER_ROLE)),
                        TreeMap::new, // supplier of sorted map
                        Collectors.mapping(
                            cellList -> UUID.fromString(cellList.get(PERMISSON_UUID)),
                            Collectors.toList())
                    ));
    

    The loop-based implementation using Map::computeIfAbsent may be as follows (an empty list is created if a roleId key is missing and the UUID is added to the list of UUIDs):

    Map<Integer, List<UUID>> userRolePermissionMap = new TreeMap<>();
    
    for (List<Cell> cellList : rowList) {
        userRolePermissionMap.computeIfAbsent(
            Integer.parseInt(cellList.get(USER_ROLE)),
            k -> new ArrayList<UUID>()
        )  // mutable List<UUID> is returned
        .add(UUID.fromString(cellList.get(PERMISSON_UUID)));
    }