哈希表 getcontainsKey 不起作用
HashTable getcontainsKey does not work
我不明白为什么这个简单的方法不起作用
我的 class AccessChecker
有属性 Hashtable<String, List<Permission>> permissions = new Hashtable<String, List<Permission>>();
有两种方法:
第一种方法
如果我把 this.permissions.containsKey(key)
放在这个方法的末尾,用一个好的密钥,它就可以工作。
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);
}
}
}
}
第二种方法
但是,当我在方法 hasAccessToWebservice()
中执行此操作时,它不适用于相同的密钥...
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;
}
你能解释一下为什么吗?
谢谢
你需要在运行ning hasAccessToWebservice
之前调用updatePermissions将所有数据放入你的权限中
如果您 运行 hasAccessToWebservice 没有 updatePermissions,则权限列表中没有任何内容 => this.permissions.containsKey(key) 无效
问题总结
总结一下题目,问题围绕着关键的一致性:
Map.containsKey(Object key)
基本会检查key
是否在Map.keySet()
中,主要是靠Object.hashCode()
您的地图键 class 是 String
。如果您查看 String.hashCode()
代码,您会发现它依赖于每个单个字符值。
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.)
值可以在 ASCII Table 中找到,突出显示 hashCode()
区分大小写
解决方案/改进
- 最简单的解决方案是确保
createKeyPermissions
方法始终生成一致的密钥,方法是将所有内容都小写
- 使用
TreeMap
with a comparator where the most fitted one is String.CASE_INSENSITIVE_ORDER
我不明白为什么这个简单的方法不起作用
我的 class AccessChecker
有属性 Hashtable<String, List<Permission>> permissions = new Hashtable<String, List<Permission>>();
有两种方法:
第一种方法
如果我把 this.permissions.containsKey(key)
放在这个方法的末尾,用一个好的密钥,它就可以工作。
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);
}
}
}
}
第二种方法
但是,当我在方法 hasAccessToWebservice()
中执行此操作时,它不适用于相同的密钥...
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;
}
你能解释一下为什么吗?
谢谢
你需要在运行ning hasAccessToWebservice
之前调用updatePermissions将所有数据放入你的权限中如果您 运行 hasAccessToWebservice 没有 updatePermissions,则权限列表中没有任何内容 => this.permissions.containsKey(key) 无效
问题总结
总结一下题目,问题围绕着关键的一致性:
Map.containsKey(Object key)
基本会检查key
是否在Map.keySet()
中,主要是靠Object.hashCode()
您的地图键 class 是
String
。如果您查看String.hashCode()
代码,您会发现它依赖于每个单个字符值。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.)
值可以在 ASCII Table 中找到,突出显示
hashCode()
区分大小写
解决方案/改进
- 最简单的解决方案是确保
createKeyPermissions
方法始终生成一致的密钥,方法是将所有内容都小写 - 使用
TreeMap
with a comparator where the most fitted one isString.CASE_INSENSITIVE_ORDER