【问题标题】:String Array as Key of HashMap字符串数组作为 HashMap 的键
【发布时间】:2016-01-14 14:10:22
【问题描述】:

我需要为我们的项目解决两个问题,其中 (1) 我必须找到一种方法可以将数组(String[] 或 int[])作为 Map 的键。要求是,如果两个数组的内容相等 (String[] a={"A","B"}, String[] b={"B","A"}) 那么它们应该被认为是相等/相同的键,即如果我使用 a 或 b 作为 Map 的键,则 a.equal(b)=true

我发现 Java Sets 添加了存储在其中的所有对象的哈希码。哈希码的添加允许比较两个哈希集,看看它们是否相等,这意味着这种机制允许根据它们的内容比较两个 java Set。

所以对于上述问题,我可以使用 Sets 作为 Map 的 Key,但问题是我想使用 Arrays 作为 Key。那么有什么想法吗?

(2) 接下来,我们对高效的部分密钥匹配机制感兴趣。例如,查看 Map 中的任何键是否包含 Array 的一部分,例如查找 Key.contains(new String[]{"A"}) 之类的东西。

请分享您的想法,任何替代方式,我关心空间和时间优化实现。因为这将用于数据流处理项目。所以空间和时间真的是个问题。

【问题讨论】:

  • 为方便起见,您最好使用Set;这样,您可以保证equalshashCode 发生的情况的行为。
  • 另见Can a java array be used as a HashMap key。正如建议的那样,您应该改用Set,因为您不能覆盖数组的equals/hashCode 的行为。
  • 好的,第二个问题呢,有什么想法吗?
  • 对于第二部分,trie(或TreeMap)可能有用:Partial search in HashMap

标签: java


【解决方案1】:

我尝试在 Java8 中使用 lambda 表达式来解决您的问题

对于问题 1:

    String[] arr1 = {"A","B","A","C","D"};
    List<String> list1 = new ArrayList<String>(new LinkedHashSet<>(Arrays.asList(arr1)));
    list1.stream().forEach(x -> System.out.println(x));

如果您想比较它们是否相等。我建议您可以先对它们进行排序,然后再进行比较。 当然,使用 Set 和 Hashcode 做比较会好很多

对于问题2(上面的一些变量将被重复使用):

    String[] arr2 = {"A"};
    List<String> list2 = new ArrayList<String>(Arrays.asList(arr2)); //Assume List2 element is also unique
    int NumOfKeyContain = list1.stream().filter(a -> (list2.stream().filter(b -> !b.equals(a)).count())<list2.size())
            .collect(Collectors.toList())
            .size();
    System.out.println(NumOfKeyContain); //NumOfKeyContain is the number that of key in list2 contained by list1

【讨论】:

  • 你读过我的任务吗?您的第一个解决方案如何有助于键映射?您只是将字符串数组添加到列表中然后打印它。
  • 如果我误解了你的问题,请澄清一下。我已经在键映射中添加了我的建议。您可以先对它们进行排序,然后快速逐个比较元素,以确定两个列表包含的键是否相等。它解决了 (String[] a={"A","B"}, String[] b={"B","A"}) 根据您的定义应该相等的目的。对于代码部分,我只是消除了重复。对于比较部分,我使用文字而不是代码。
  • 我需要将它们用作 HashMap 的键,所以真正的问题是解决这个问题
【解决方案2】:

Q1 - 如果您希望基于数组元素的键相等,则不能使用裸数组作为 HashMap 键。数组从java.lang.Object 继承equals(Object)hashCode() 实现,它们基于对象标识,而不是数组内容。

我能想到的最佳选择是将数组包装为(不可变的)列表。

Q2 - 我认为没有一种简单有效的方法可以做到这一点。我能想到的最好的是:

  • 提取每个数组的所有可能子数组,并使每个子数组成为哈希表中的备用键。问题是键将占用O(N M^2) 空间,其中M 是主键String[] 中字符串的平均(?)数。查找仍将是 O(1)

  • 建立一个倒排索引,给出每个字符串在所有键中的位置,然后对键空间中的一系列字符串进行“短语搜索”。就空间使用而言,这应该可以更好地扩展,但查找成本要高得多。而且很复杂。

【讨论】:

    猜你喜欢
    • 2013-11-17
    • 1970-01-01
    • 2014-07-03
    • 1970-01-01
    • 2014-02-26
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    相关资源
    最近更新 更多