可互换的键/值 HashMap Set 结构

发布于 2024-11-03 17:22:45 字数 1218 浏览 0 评论 0原文

背景

使用两个操作数创建一系列 SQL JOIN 语句:主操作数和辅助操作数。 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 );
}

其中,如果 primaryOperand 映射到,则 interchangeableMap.contains(...) 将返回 true secondaryOperand secondaryOperand 映射到primaryOperand

问题

  1. Java 库中是否存在这样的数据结构?
  2. 如果没有,您将使用什么数据结构来实现?

想法

我的第一个想法是创建一个包含两个 HashMap 的类。检查包含性时会查询两个 HashMap,以查看一个映射是否包含主要和次要操作数,或者另一个映射是否包含次要和主要操作数。插入将两个操作数组合放入各自的 HashMap 中。

谢谢你!

Background

Create a series of SQL JOIN statements using two operands: primary and secondary. The generic form of the JOIN statement is:

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

Problem

The code currently iterates over a list of primary and secondary operands, as follows:

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

The problem is that the nested loop generates the following:

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

The second join is superfluous and, in this case, causes an error. The duplication can be eliminated with the following hypothetical data structure:

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

    outputJoin( primaryOperand, secondaryOperand );
}

Where interchangeableMap.contains(...) will return true if primaryOperand is mapped to secondaryOperand or secondaryOperand is mapped to primaryOperand.

Questions

  1. Does such a data structure exist in the Java libraries?
  2. If not, what data structures would you use for its implementation?

Ideas

My first thought is to create a class that contains two HashMaps. Checking for containment queries the two HashMaps to see if one map contains the primary and secondary operands or the other map contains the secondary and primary operands. Insertions put the two operand combinations into their respective HashMaps.

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

用心笑 2024-11-10 17:22:45

这是基于 @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() 方法(哈希值必须反映等式关系),但必须采用对称的方式,即: 的哈希值必须与 的哈希值 == 。

Here is a solution based on @roland's suggestion:

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

Then:

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

A subtle point about the solution: you must also override the hashCode() method (hash value must reflect the equality relation), but you must do it in a symmetric way, that is: the hash value of <a,b> must be == to that of <b,a>

攒眉千度 2024-11-10 17:22:45

另一个想法是定义一个新的类OperatorPair,它重写equals()并使用其中的Set,再次使用进行检查>包含()。但你的解决方案也应该运作良好。

(另外,如果你这样做,你也应该覆盖 hashCode() ,例如你可以根据操作数的名称来计算它......参见例如 这个问题了解详细信息。)

Another idea would be to define a new Class OperatorPair that overrides equals() and use a Set of those, again to be checked with contains(). But your solution should work well, too.

(Also, if you do this, you should override hashCode() as well, for example you could calculate it based on the names of the operands... see e.g. this question for details.)

甜心 2024-11-10 17:22:45

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

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

I hope I'm not completely wrong:
You can use a HashMap and put each mapping twice: (primary, secondary) and (secondary, primary). For a lookup you would not check for contains but (get(primary) == seconday) or (get(secondary) == primary).

The apache commons library contains the BidiMap which allows a "bidirectional lookup between key and values". So you use this one too, to avoid the double insert

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文