javahashtablecontainskey

HashTable getcontainsKey does not work


I don't understand why this simple method does not work

My class AccessChecker has the attribute Hashtable<String, List<Permission>> permissions = new Hashtable<String, List<Permission>>(); with two methods:

First method

If I put this.permissions.containsKey(key) at the end of this method , with a good key, it works.

public void updatePermissions() {
    List<Permission> permissionsTmp = permissionRepository.findAllWithEagerRelationships();

    // clear permissions
    this.permissions = new Hashtable<>();

    // load all permissions
    for (Permission permission : permissionsTmp) {
        Profil profil = profilRepository.findOne(permission.getProfil().getId());
        permission.setProfil(profil);
        UserFonc user = userFoncRepository.findOne(permission.getUserFonc().getId());
        permission.setUserFonc(user);

        log.error("updatePermissions ** user login = " + user.getNom());

        for (WebService webService: profil.getWebServices()) {
            String key = createKeyPermissions(user.getNom().toLowerCase(), webService.getNom(), webService.getMethode());
            log.error("updatePermissions ** key = " + key);
            if (this.permissions.containsKey(key)){
                this.permissions.get(key).add(permission);
            }
            else {
                List<Permission> newPermissions = new ArrayList<>();
                newPermissions.add(permission);
                this.permissions.put(key, newPermissions);
            }

        }
    }
}

Second method

But, when I do this in method hasAccessToWebservice(), it does NOT work for the same key...

public boolean hasAccessToWebservice(HttpServletRequest request) {
    boolean hasAccess = false;

    String webservice = getServiceFromRequest(request);
    String methode = request.getMethod();
    String login = SecurityUtils.getCurrentUserLogin();
    String userAgent = request.getHeader(Constants.USER_AGENT);

    final String userLogin = SecurityUtils.getCurrentUserLogin();
    log.error("hasAccessToWebservice ** user login = " + userLogin);

    String key = createKeyPermissions(login.toLowerCase(), webservice, methode);
    log.error("hasAccessToWebservice ** key = " + key);

    log.error("hasAccessToWebservice ** element = " + this.permissions.size());

    Set t = this.permissions.keySet();
    log.error(t.toString());

    if (this.permissions.containsKey(key)) {
        log.error("hasAccessToWebservice ** key found !!");
        hasAccess = true;
    }
    return hasAccess;
}

Can you explain why?

Thank you


Solution

  • Problem summary

    To summarise the topic, the problem revolved around the key consistency:

    1. Map.containsKey(Object key) will basically check if key is among the Map.keySet() mainly by relying on Object.hashCode()
    2. Your map key class is String. If you look at String.hashCode() code, you'll see that it relies on each single character value.

      Returns a hash code for this string. The hash code for a String object is computed as

      s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

      using int arithmetic, where s[i] is the ith character of the string, n is the length of the string, and ^ indicates exponentiation. (The hash value of the empty string is zero.)

      Value can be found in the ASCII Table highlighting that hashCode() is case-sensitive

    Solution / Improvement