【问题标题】:Is there an efficient way to check if a key stored in a HashMap is equal to a test key when the keys are `String[]`? [duplicate]当键是`String []`时,是否有一种有效的方法来检查存储在HashMap中的键是否等于测试键? [复制]
【发布时间】:2014-09-14 20:02:26
【问题描述】:

我遇到了性能问题,因为为了检索某个键的值,我必须检查存储在映射中的每个键是否等于我的测试键。性能问题源于我必须覆盖地图的 get 操作,该操作检查地图是否具有测试密钥。我的键需要某种元组,我使用String[] 来存储两个Strings。这是我的带地图的课程。

public class ClassWithMap {

    Map<String[], Double> arrayToDoubleMap;

    public ClassWithMap() {
        arrayToDoubleMap = new HashMap<String[], Double>() {
            @Override
            public Double get(Object key) {
                String[] stringArray = (String[]) key;

                Set<String[]> keySet = this.keySet();
                for (String[] tuple : keySet) {
                    if (tuple[0].equals(stringArray[0]) && tuple[1].equals(stringArray[1])) {
                        key = tuple;
                        break;
                    }
                }

                return super.get(key);
            }
        };
    }

    public Double getDouble(String string1, String string2) {

        String[] tuple = { string1, string2 };
        return (Double) arrayToDoubleMap.get(tuple);

    }
}

这里有一些测试方法。

public static void main(String[] args) {

    ClassWithMap map = new ClassWithMap();
    String[] tuple1 = { "foo", "bar" };
    map.arrayToDoubleMap.put(tuple1, 0.0);

    String[] tuple2 = { "fee", "fum" };
    map.arrayToDoubleMap.put(tuple2, 1.0);

    System.out.println(map.getDouble("fee", "fum"));

}

如果我不覆盖映射声明中的get 操作,我会得到null,因为String[] 键与测试String[] 键不完全相同。

所以我的问题是:有没有比创建一个检查每个键和测试键之间是否匹配的方法更有效的方法来强制此对象等效?

【问题讨论】:

  • 你可以创建一个不同的类,称之为StringTuple,它是一个包含两个字符串的对象。您可以通过比较字符串相等性来实现compareTo() / equals()
  • 你不应该像那样覆盖核心功能(它一定会导致悲伤)。相反,将String[] 包装在一个简单的类中,该类适当地实现equals()hashcode()
  • @OliCharlesworth,那么为什么可以在这个新类中覆盖equals(),但不能在这个地图类中覆盖get()?您如何定义“核心功能”?
  • @ijkilchenko:好问题。我想答案是“因为 HashMap.get 不是为了被覆盖而设计的”。可能存在依赖get 以特定方式工作的内部实现细节,您现在可能已经违反了。另一方面,equals 非常适合被覆盖。然后你可以争辩说HashMap.get 应该标记为final,我同意。
  • @OliCharlesworth,这不一定是我会详述的,但是如果您再次查看我的覆盖,它只会更改随后传递给 super.get() 方法的对象。所以我最终不会违反太多。

标签: java oop data-structures map


【解决方案1】:

您可能应该创建一个类来保存这两个字符串,而不是将它们放在一个数组中:

class StringPair {
    private final String str1, str2;

    public StringPair(final String str1, final String str2) {
        this.str1 = str1;
        this.str2 = str2;
    }

    public String getStr1() {
        return str1;
    }

    public String getStr2() {
        return str2;
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof StringPair))
            return false;

        StringPair sp = (StringPair) o;
        return Objects.equals(str1, sp.str1) && Objects.equals(str2, sp.str2);
    }

    @Override
    public int hashCode() {
        return Arrays.asList(str1, str2).hashCode();
    }
}

现在,您将使用Map&lt;StringPair, Double&gt;

【讨论】:

  • 据我所知,不建议或不安全地进行显式转换。 :)
  • @KickButtowski 你为什么这么说?
  • 我只是分享了我被告知要查看他人意见的内容。我能想到的唯一原因是精度损失,而且我确定其他问题我现在不记得了。如果你注意,我说据我所知,所以这并不意味着我是对的或错的。 ;)
  • @KickButtowski 选角有没有的问题,equals 真的别无选择。我只是好奇是什么让你相信铸造是不好的做法......
  • @KickButtowski,在那里转换应该没有问题,因为他会检查对象是否是StringPair 的实例。只有作为 StringPair 实例的对象才会到达强制转换语句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-26
  • 1970-01-01
  • 2011-05-13
  • 1970-01-01
  • 1970-01-01
  • 2014-12-19
相关资源
最近更新 更多