繁体   English   中英

在HashMap中搜索子类的键

[英]searching keys of subclass in HashMap

只是试图做类似的事情:

public class GameMap {

protected HashMap<Sector, Integer[]> mapping;

protected void loadMapFromFile(String fileLocation, int numPlayers) {

    .
    //Other stuff
    .
    .

    case "ALIENSECT":

    Integer[] someValue = {5};
    mapping.put(new AlienSector(row, col), someValue);
    break;
}

public justATestMethod() {

    System.out.println(mapping.containsKey(new Sector(6, 'L')));
}

其中AlienSectorSector的子类。

但是当我尝试在另一堂课中这样做时:

   mappa.justATestMethod();

结果为“假”。

相反,如果我这样重写方法“ justATestMethod()”:

System.out.println(mapping.containsKey(new AlienSector(6, 'L')));

结果为“ true”。

我也更改了“ loadMapFromFile”方法的这一行,获得“ true”:

case "ALIENSECT":

Integer[] someValue = {5};
mapping.put(new AlienSector(row, col), someValue);
break;

这条路:

case "ALIENSECT":

mapping.put(new Sector(row, col), new Integer[1]);
Integer[] aCazzo = {5};
mapping.put(new AlienSector(row, col), aCazzo);
break;

那就是先用Sector对象键填充HashMap,然后分配AlienSector对象键。

有人可以解释我为什么会这样吗? AlienSector是的子类Sector ,为什么Java不识别存在Sector在HashMap的键,如果我只要实现它的一个子类,而第一实例化超“部门”本身的istance的关键?

您正在将AlienSector存储在HashMap中,然后尝试使用使用相同参数创建的另一个Sector来检索它。 当您尝试从HashMap检索对象时, 它正在寻找的对象与您存储的对象“相等” 但是默认情况下,Java不会仅仅因为两个对象具有相同的成员就将它们识别为“相等”。 默认情况下,仅当它们是相同的对象时它们才相等 (字符串,整数等是特殊情况)。

您需要做的是通过覆盖'equals'方法来告诉Java具有相同参数的两个对象是'equal'。 从测试结果看来,您已经为AlienSector完成了此操作。 但是您将需要对Sector和AlienSector都执行此操作,并对其进行安排,以便即使对象具有不同的类,也认为它们是相等的,即AlienSector被视为等于具有相同成员的Sector,而Sector被视为等于一个Sector。具有相同成员的AlienSector。 有关于如何执行此操作的教程。

您还需要重写hashCode()方法 ,以确保将被视为“相等”的任何两个对象也返回相同的hashCode。 HashMap使用hashCode过滤器,确定具有不同hashCodes的事物永远不会相等。

所有这些细节太长了,无法给出这样的答案。

顺便说一句,如果您在containsKey调用中使用了相同的对象 ,而不是创建一个新的对象,您会发现它起作用。

您可以使用下面的类执行此行为。

需要注意的一点是,如果地图很大,则性能可能不会特别好,但是在大多数情况下,地图的大小会很小,因此不会对性能产生实际影响。

注意:JDK8 +代码

本质上,我们为containsKey覆盖了常规的hashmap类方法,并进行了适当的搜索。

import java.util.HashMap;
import java.util.Optional;

public class PolymorphicHashMap<K extends Class<?>,V> extends HashMap<K,V> {

  @Override
  public boolean containsKey(Object key) {
    return findEntry((K)key).isPresent();
  }

  @Override
  public V get(Object key) {
    var entry = findEntry((K)key);
    return entry.map(Entry::getValue).orElse(null);
  }

  private Optional<Entry<K,V>> findEntry(K key) {
    return entrySet().stream()
        .filter(e -> e.getKey().isAssignableFrom(key))
        .findFirst();
  }

}

HashMap使用hashCode()函数以查找和存储键/值对。
我相信您需要使超类/子类都返回相同的哈希码,以便能够在HashMap中查找子类的键。

public class AlienSector {
    public int hashcode() {
        //
        // Generate a hashcode unique to this AlienSector object here
        //
    }
}

public class Sector {
    public int hashCode() {
        return super.hashCode(); // Return the same hashcode as the super class
    }
}

正如评论中指出的那样,规则是,如果您覆盖hashCode()函数,则还需要覆盖equals()函数(反之亦然)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM