基于散列的HashMap密钥生成 [英] HashMap key generation based on hashing

查看:176
本文介绍了基于散列的HashMap密钥生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的意图是为数据库结果创建一个缓存服务,以便根据客户端的请求进行不同的分页。

因此,根据(搜索)请求,我我正在制作一个由参数组成的密钥,这些参数的格式为 Map< String,String []> 和a:

  public class DocMaintainer {
public Manipulator creator;
public Manipulator lastChange;

@Override
public boolean equals(Object o){
if(this == o)return true;
if(o == null || getClass()!= o.getClass())return false;
DocMaintainer that =(DocMaintainer)o;
返回Objects.equals(creator,that.creator)&&
Objects.equals(lastChange,that.lastChange);

$ b @Override
public int hashCode(){

return Objects.hash(creator,lastChange);
}
}


public class Manipulator {
public Date fromDate;
public Date toDate;
public String userId;
public String system;

public Manipulator(){
this.userId =;
this.system =;
this._fromJoda = new DateTime(Long.MIN_VALUE);
this._toJoda = new DateTime(Long.MAX_VALUE - DateTimeConstants.MILLIS_PER_WEEK);
}

私人日期时间_fromJoda;
私人日期时间_toJoda;

public DateTime get_fromJoda(){
_fromJoda = fromDate!= null?新的DateTime(fromDate):_fromJoda;
return _fromJoda;
}

public DateTime get_toJoda(){
_toJoda = toDate!= null?新的DateTime(toDate):_toJoda;
尝试{
_toJoda = _toJoda.plusDays(1);
} catch(Exception e){
System.out.println(e);
}

return _toJoda;
}

@Override
public boolean equals(Object o){
if(this == o)return true;
if(o == null || getClass()!= o.getClass())return false;
Manipulator that =(Manipulator)o;
返回Objects.equals(fromDate,that.fromDate)&&
Objects.equals(toDate,that.toDate)&&
Objects.equals(userId,that.userId)&&
Objects.equals(system,that.system);

$ b @Override
public int hashCode(){

return Objects.hash(fromDate,toDate,userId,system);






$ b你可以看到我打算使用哈希创建一个键:

pre $ public class SearchKey {
public int conjunctionHash;
public int disjunctionHash;
public int maintainerHash;

公共SearchKey(int结合哈希,int disjunctionHash,int维护者哈希){
this.conjunctionHash = conjunctionHash;
this.disjunctionHash = disjunctionHash;
this.maintainerHash = maintainerHash;
}

@Override
public boolean equals(Object o){
if(this == o)return true;
if(o == null || getClass()!= o.getClass())return false;
SearchKey searchKey =(SearchKey)o;
return connectHash == searchKey.conjunctionHash&&
disjunctionHash == searchKey.disjunctionHash&&
maintainerHash == searchKey.maintainerHash;

$ b @Override
public int hashCode(){

return Objects.hash(conjunctionHash,disjunctionHash,maintainerHash);


键对象直接用作缓存键在单件服务中:

  @命名
@Singleton
公共类SearchCacheSrv {

私人地图< SearchKey,ValidMainteinersList< FindDTO>> cache = new HashMap<>();

public ValidMainteinersList< FindDTO> getCached(SearchKey searchKey){
if(cache.containsKey(searchKey))
return cache.get(searchKey);
else
返回新的ValidMainteinersList< FindDTO>();

$ b public SearchKey makeAkey(Map< String,String []>连接,
Map< String,String []>析取,
DocMaintainer维护者) {
返回新的SearchKey(合成.hashCode(),disjunction.hashCode(),maintainer.hashCode());
}

public ValidMainteinersList< FindDTO> (SearchKey searchKey,ValidMainteinersList< FindDTO> findDTOS){
return cache.put(searchKey,findDTOS);
}

public void clearCache(){
cache.clear();






$ b

不幸的是,这不符合我的预期,而我'

当然问题是为什么?

解决方案

这里的问题是数组的 hashCode 不取决于内容,而取决于参考资料。这意味着如果你有两个相同的键/分离键,但是包含的数组不是相同的对象,那么键的哈希码将会不同。



可能花费最少精力的解决方案是用 ArrayList s替换数组,这些数组的基础是它们的 hashCode a href =https://docs.oracle.com/javase/7/docs/api/java/util/List.html#hashCode() =nofollow noreferrer>内容。


My intention was to make a caching service for a database results, that I can paginate differently based on client's requests.

So, upon the (search) request I am making a key that is composed of parameters, which are in form of two Map<String, String[]> and a:

public class DocMaintainer {
    public Manipulator creator;
    public Manipulator lastChange;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DocMaintainer that = (DocMaintainer) o;
        return Objects.equals(creator, that.creator) &&
                Objects.equals(lastChange, that.lastChange);
    }

    @Override
    public int hashCode() {

        return Objects.hash(creator, lastChange);
    }
}


public class Manipulator {
    public Date fromDate;
    public Date toDate;
    public String userId;
    public String system;

    public Manipulator() {
        this.userId = "";
        this.system = "";
        this._fromJoda = new DateTime(Long.MIN_VALUE);
        this._toJoda = new DateTime(Long.MAX_VALUE - DateTimeConstants.MILLIS_PER_WEEK);
    }

    private DateTime _fromJoda;
    private DateTime _toJoda;

    public DateTime get_fromJoda() {
        _fromJoda = fromDate != null ? new DateTime(fromDate) : _fromJoda;
        return _fromJoda;
    }

    public DateTime get_toJoda() {
        _toJoda = toDate != null ? new DateTime(toDate) : _toJoda;
        try {
            _toJoda = _toJoda.plusDays(1);
        } catch (Exception e) {
            System.out.println(e);
        }

        return _toJoda;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Manipulator that = (Manipulator) o;
        return Objects.equals(fromDate, that.fromDate) &&
                Objects.equals(toDate, that.toDate) &&
                Objects.equals(userId, that.userId) &&
                Objects.equals(system, that.system);
    }

    @Override
    public int hashCode() {

        return Objects.hash(fromDate, toDate, userId, system);
    }
}

As you can see I intended to use hashing to create a "key":

public class SearchKey {
    public int conjunctionHash;
    public int disjunctionHash;
    public int maintainerHash;

    public SearchKey(int conjunctionHash, int disjunctionHash, int maintainerHash) {
        this.conjunctionHash = conjunctionHash;
        this.disjunctionHash = disjunctionHash;
        this.maintainerHash = maintainerHash;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        SearchKey searchKey = (SearchKey) o;
        return conjunctionHash == searchKey.conjunctionHash &&
                disjunctionHash == searchKey.disjunctionHash &&
                maintainerHash == searchKey.maintainerHash;
    }

    @Override
    public int hashCode() {

        return Objects.hash(conjunctionHash, disjunctionHash, maintainerHash);
    }
}

a key-object is used directly as a caching key in a singleton service:

@Named
@Singleton
public class SearchCacheSrv {

    private Map<SearchKey, ValidMainteinersList<FindDTO>> cache = new HashMap<>();

    public ValidMainteinersList<FindDTO> getCached(SearchKey searchKey) {
        if (cache.containsKey(searchKey))
            return cache.get(searchKey);
        else
            return new ValidMainteinersList<FindDTO>();
    }

    public SearchKey makeAkey(Map<String, String[]> conjunction,
                              Map<String, String[]> disjunction,
                              DocMaintainer maintainer) {
        return new SearchKey(conjunction.hashCode(), disjunction.hashCode(), maintainer.hashCode());
    }

    public ValidMainteinersList<FindDTO> cache(SearchKey searchKey, ValidMainteinersList<FindDTO> findDTOS) {
        return cache.put(searchKey, findDTOS);
    }

    public void clearCache() {
        cache.clear();
    }
}

Unfortunately this is not behaving the way I expected and I'm getting different hashes/keys generated for the same parameters.

Naturally question is why?

解决方案

The problem here is that the hashCode of an array does not depend on the contents, but on the reference. That means that if you have two conjunction / disjunction keys that are equal, but the contained arrays are not the same objects, then the hashcode of the keys will be different.

The solution that probably takes the least effort is replacing the arrays with ArrayLists, which do base their hashCode on the content.

这篇关于基于散列的HashMap密钥生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆