【问题标题】:HashMap key generation based on hashing基于散列的HashMap密钥生成
【发布时间】:2018-08-31 14:55:59
【问题描述】:

我的目的是为数据库结果提供缓存服务,我可以根据客户的请求进行不同的分页。

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

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);
    }
}

如您所见,我打算使用散列来创建“密钥”:

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);
    }
}

key-object 直接用作单例服务中的缓存键:

@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();
    }
}

不幸的是,这不是我预期的方式,我得到了为相同参数生成的不同哈希/键。

问题自然是为什么?

【问题讨论】:

  • “很遗憾,这与我预期的不一样” 您期待什么?它表现如何?
  • 在 Java 应用程序执行期间,只要在同一个对象上多次调用它,hashCode 方法必须始终返回相同的整数,前提是没有修改对象上相等比较中使用的信息。此整数不必从应用程序的一次执行到同一应用程序的另一次执行保持一致。
  • 嗯,就是这样,但这是怎么回事?一个对象的实例是否在其中扮演了某种角色?有什么建议我怎样才能让它服务于我的目的?
  • 请提供minimal reproducible example,说明您如何使用此代码,提供示例输入、预期和实际输出。
  • 你列出了我的每个课程。你要我做什么?引导部署到 plunker 上的 tomcat 的企业 Java 后端?获得一些真实的生活

标签: java hash


【解决方案1】:

这里的问题是数组does not depend on the contents, but on the referencehashCode。这意味着如果你有两个相等的合取/析取键,但包含的数组不是相同的对象,那么键的哈希码就会不同。

可能最省力的解决方案是用ArrayLists 替换数组,它们的hashCode 确实基于content

【讨论】:

    【解决方案2】:

    实际上,我没有看到将 conjunction.hashCode(), ... 传递给您的 SearchKey 构造函数的意义;我从来没有这样做过,但这可能是我的错误。 尝试将实际值传递给您的 SearchKey 类,而不是 hashCodes,这样 hashCode 方法总是返回一个一致的值。

    【讨论】:

    • 是的,这样更简洁,我这样做的原因是更明确和更易于阅读。当然,这不是我的问题的解决方案,但已被接受的答案解决了;
    猜你喜欢
    • 1970-01-01
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    相关资源
    最近更新 更多