【问题标题】:Get matching object type from HashMap从 HashMap 获取匹配的对象类型
【发布时间】:2017-02-05 21:01:27
【问题描述】:

首先我想说我对编程还很陌生。 我在同一个 HashMap 中存储了一些超类的“扩展”。 (例如 XY 和 XZ 扩展了 X - 我将 X、XY 和 XZ 都存储在同一个 HashMap 中)。 我决定这样做是为了方便——通常每次我做某事时,我都需要扩展“X”的所有类——在这个例子中是“XY”和“XZ”。当我想检查单个值是否是指定类型对象的实例时也没有问题 - 我只是使用“instanceof”公式。假设我想检查键“key”的对象是否是“XY”的实例:

X objectoftypeX = hashmap.get(key)
if(objectoftypeX instanceof XY){
    //do stuff
}

但是我的问题来了:如何只遍历这个 HashMap 中的 XY? 如果不单独检查每个对象,这可能吗? 这样做有意义吗? 希望你能理解我的问题。

【问题讨论】:

    标签: java loops hashmap


    【解决方案1】:

    地图是一种相当简单的结构,可以优化一种访问形式(按键查找)。如果您希望能够快速找到特定类型的项目,那么您需要使用不同的结构。

    例如,您可以选择制作多张地图,或者制作嵌套地图:

    // Nested map, with the top level map indexing by Type (can be a String)
    // and the maps inside it indexing by a String key.
    Map<Type, Map<String, Object>> map = ...;
    

    如果您不介意单独检查每个条目的开销,您可以通过流轻松获取所需的所有元素:

    List<XY> list = hashmap.values().stream()
        .filter(v -> v instanceof XY)  // check type
        .map(v -> (XY) v)   // do cast
        .collect(Collectors.toList());  // collect to list
    

    【讨论】:

      【解决方案2】:
      hashmap.entrySet().filter(item -> item.value() instanceOf X).forEach(item -> ...);
      

      都是一样的,但是射手

      【讨论】:

      • 我认为这些键的类型不是 X、XY、XZ :)
      • 谢谢)只是打错了,修复了
      【解决方案3】:
          final Object[] keySetArray = mMap.keySet().toArray();
      for( int x = 0; x < keySetArray.length; x++ )
      {
              final Object whatStored = mMap.get( keySetArray[x] );
              System.out.println("key[" + keySetArray[x] + "]: "+ whatStored );
          // Make sure this check happens as it is, if you stored XY and XZ that extended X  
               if( whatStored instanceof of XY || whatStored instanceof XZ )
               {
                   if( whatStored instanceof XY )
                   {
                        // Go here for instance X and XY
                   }
                   else if( whatStored instanceof XZ )
                   {
                       // Go here for instance X and XZ
                   }
               }
      }
      

      希望这是关闭??

      【讨论】:

      • 我认为它很接近,但比需要的更复杂。
      【解决方案4】:

      使用标准的 hashmap 不可能有效地做到这一点(无需经历所有事情)。 hashmap 的目的是提供对元素的快速访问,而内存开销很小。考虑你有一个整数大小的数组和一个哈希码函数,它为每个存储的对象返回整数。然后,您将能够通过应用 index = hashcode(key) 找到元素,这基本上是 1 个操作来查找任何内容。但是你有一个可怕的内存开销(数组大小等于所有整数)。

      其他选项是有一个列表并遍历所有元素。在这里您不会有内存开销,但搜索复杂度将是 O(n) - 您需要遍历所有内容以确保该元素不在数组中(或尽快找到它)。

      Hashmap 在中间。您分配大小的数组,假设为 100。然后计算键的哈希码函数,结果为 105。因此,您将对象放在索引 {hashcode_result} 模数组大小上。在我们的例子中 105 % 100 == 5。

      有趣的东西取决于实现,你会做什么,如果你有一个碰撞,它作为一个 key2 具有相同的位置。例如,如果哈希码值为 205、305...(对于所有这些哈希码,模数将为 5)。 一种可能性是将这些附加元素添加到下一个可用索引 6、7... 在 java 中(或者至少据我所知),桶是作为链表实现的,所以你将拥有

      0 => []
      1 => []
      2 => []
      3 => []
      4 => []
      5 => [k=105, k=205, k=305...]  
      

      在你的用例中使用 hashmap 的唯一方法是实现一个 hashcode 函数,它总是为同一个类生成相同的 hash。但这会将哈希图退化为 n 个列表,其中 n 是子类的数量。并且查找将受到严重影响(您将不得不执行 M/n 操作来查找值,其中 M 是元素的数量,n 是不同类的数量),而正确实现的 hashmap(hashcode 值的均匀分布)保证查找次数实际上等于 1。


      长话短说 - 由于 hashmap 的结构,您无法有效地执行任何类型的数据相关 loopkup(您会破坏搜索列表的性能)。 如果你想进行这种类型的查找,john16384的答案是一个非常好的答案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-18
        • 1970-01-01
        • 1970-01-01
        • 2021-09-26
        相关资源
        最近更新 更多