可互换的键/值HashMap Set结构

时间:2011-04-29 06:24:00

标签: java algorithm data-structures

背景

使用两个操作数创建一系列SQL JOIN语句:primary和secondary。 JOIN语句的通用形式是:

JOIN primary primary ON (secondary.id == primary.id)

问题

代码当前迭代主要和辅助操作数列表,如下所示:

for( Bundle primaryOperand : bundleComparators ) {
  for( Bundle secondaryOperand : sortedBundles ) {

问题是嵌套循环生成以下内容:

JOIN primary primary ON (secondary.id == primary.id)
JOIN secondary secondary ON (primary.id == secondary.id)

第二次连接是多余的,在这种情况下,会导致错误。可以使用以下假设数据结构消除重复:

if( !interchangeableMap.contains( primaryOperand, secondaryOperand ) ) {
    interchangeableMap.put( primaryOperand, secondaryOperand );

    outputJoin( primaryOperand, secondaryOperand );
}

如果interchangeableMap.contains(...)映射到primaryOperand secondaryOperand映射到{secondaryOperandprimaryOperand将返回 true {1}}。

问题

  1. Java库中是否存在这样的数据结构?
  2. 如果没有,您将使用哪些数据结构进行实施?
  3. 我的第一个想法是创建一个包含两个HashMap的类。检查包含查询两个HashMap以查看一个映射是否包含主操作数和辅助操作数,或者另一个映射包含辅助操作数和主操作数。插入将两个操作数组合放入各自的HashMap s。

    谢谢!

3 个答案:

答案 0 :(得分:5)

以下是基于@ roland 建议的解决方案:

public final class Pair {
  private final Object a;
  private final Object b;

  public Pair(Object a, Object b) {
    this.a = a; 
    this.b = b;
  }

  @Override public boolean equals(Object o) {
    if(o == null || !(o instanceof Pair)) 
      return false;

    Pair that = (Pair) o;
    return this.a.equals(that.a) && this.b.equals(that.b) 
      || this.a.equals(that.b) && this.b.equals(that.a);
  }

  @Override public int hashCode() {
    return a.hashCode() ^ b.hashCode();
  }
}

然后:

Set<Pair> set = new HashSet<Pair>();
for(Bundle primaryOperand : bundleComparators) {
  for(Bundle secondaryOperand : sortedBundles) {
    Pair p = new Pair(primaryOperand.id, secondaryOperand.id);
    if(set.contains(p)) 
      continue;

    set.add(p);
    outputJoin(primaryOperand, secondaryOperand);
  }
}

关于解决方案的一个微妙之处:您还必须覆盖hashCode()方法(哈希值必须反映相等关系),但您必须以对称方式执行,即:{{的哈希值1}}必须==与<a,b>

的==

答案 1 :(得分:1)

另一个想法是定义一个新的OperatorPair类,它会覆盖equals()并使用Setcontains(),再次使用hashCode()进行检查。但是你的解决方案也应该运作良好。

(另外,如果你这样做,你也应该覆盖{{1}},例如你可以根据操作数的名称计算它......详见this question。)< / p>

答案 2 :(得分:1)

我希望我并非完全错误: 您可以使用HashMap并将每个映射放置两次:(primary, secondary)(secondary, primary)。对于查找,您不会检查contains,而是(get(primary) == seconday) or (get(secondary) == primary)

apache commons库包含BidiMap,它允许“键和值之间的双向查找”。所以你也使用这个,以避免双重插入