更好的hashCode函数用于股票代码符号?

时间:2016-04-08 17:53:46

标签: java hash hashmap hashcode

我正在HashMap中保存库存对象,其中键是代码符号String(例如Apple,Inc。的"AAPL")。不幸的是,这是不可行的,因为Ally Financial Inc(GM1)和Global Partners LP(GLP)有冲突的哈希码,并且会相互覆盖。例如:"GM1".hashCode() == "GLP".hashCode() ==主要问题。

股票代码字符串是否有hashCode可以保证不会发生冲突?

public Class StockTicker {
    public String symbol;

    public StockTicker(String symbol) { this.symbol = symbol; }

    @Override
    public int hashCode() {
        // What goes here?
    }
}

成功的答案可能会利用自动收报机字符串不超过5个字符的事实,并且将是大写字母数字,但“。”除外。如“BRK.B”。

2 个答案:

答案 0 :(得分:4)

我认为关键字符串的hashCode对地图本身没有任何影响(我假设您使用密钥的实际股票代码字符串,而不是哈希代码;如果您插入地图使用哈希码,然后是,这将导致问题)。我跑了一个快速测试,运行正常。

private Map<String, String> stockMap = new HashMap<String, String>();

@Test
public void mapTest() {
    stockMap.put("GM1", "gm1stock");
    stockMap.put("GLP", "glpstock");

    assertEquals(2, stockMap.size());
}

就像Mshnik所说,Java会为你处理碰撞,所以你不需要担心。你能详细说明具体导致你问题的代码吗?

答案 1 :(得分:2)

正如其他答案和评论所指出的那样,A)Java将正确处理冲突,假设您以一种令人愉快的方式编写了equals和hashcode,并且B)即使获得完美的哈希码函数并不能保证您不会得到碰撞。

据说,可以为您的规范编写完美的哈希码函数。您需要担心的是37个字符(26个字母,10个数字和.),小于64.因此我们可以使用6位来表示每个字符。您最多有5个字符,这意味着您的哈希码最多需要30位,这符合int。

这是一个创建完美哈希码的实现:

  public static class Stock{
    // The possible characters of a stock - note length is < 64
    private final static String alphaNumeric = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.";

    //Will be 6 for given valid chars, but coding it like this prevents bugs later
    private final static int shiftAmnt = (int)(Math.log(alphaNumeric.length()) / Math.log(2)) + 1;

    private String stock;

    public Stock(String s) {
      stock = s;
    }

    @Override
    public boolean equals(Object o) {
      return o instanceof Stock && stock.equals( ((Stock)o).stock);
    }

    @Override
    public int hashCode() {
      int code = 0;
      for (char c : stock.toCharArray()) {
        code = code << shiftAmnt;
        code += alphaNumeric.indexOf(c);
      }
      return code;
    }
  }