java - 这个设计有什么问题?覆盖或重载 java.util.HashMap

标签 java programming-languages collections

这个问题是在 MS 面试中问我的。我想知道这段代码中的确切设计问题。代码已经给出,需要找到设计问题。

我有 MyHashMap 类,它扩展了 java HashMap 类。在 MyHashMap 类中,我必须保留一些员工信息。此 map 中的键将为 firstName+lastName+Address 。

public MyHashMap extends HashMap<Object, Object> {
  //some member variables 
  //
  public void put(String firstName, String lastName, String Address, Object obj) {
       String key =   firstName + lastName+ Address;
       put(key, obj);
  }

  public Object get(String firstName, String lastName, String Address) {
       String key =   firstName + lastName+ Address;
       return get(key);
  }

  public void remove(Strig key) {
        put(key, ""); 
  }

  //some more methods 
}

这个设计有什么问题?我应该继承 HashMap 还是应该声明 HashMap 作为这个类的成员变量?或者我应该实现 hashCode/equals 方法吗?

最佳答案

有很多问题,但我能看到的最大问题是您使用连接的 String 作为键。下面两个调用是不同的,但是是等价的:

final MyHashMap map = new MyHashMap();

map.put("foo", "", "baz", new Object());
map.put("", "foo", "baz", new Object()); // Overwrites the previous call

还有一个问题是,您将键类型声明为 Object,但始终使用 String,因此没有利用随之而来的类型安全性与泛型。例如,如果您想遍历 MapkeySet,则必须将每个 Set 条目转换为 String,但您无法确定是否有人滥用您的 Map,例如使用 Integer 键。

就我个人而言,除非您有充分的理由不这样做,否则我赞成组合而不是继承。在您的情况下,MyHashMap 正在重载putget 的标准Map 方法和删除,但不覆盖它们中的任何一个。你应该继承一个类来改变它的行为,但是你的实现并没有这样做,所以组合是一个明确的选择。

举个例子,重载而不是覆盖意味着如果你做出以下声明:

Map<Object, Object> map = new MyHashMap();

没有您声明的方法将可用。正如其他一些答案所建议的那样,最好使用由 firstName、lastName 和 address 组成的对象作为映射键,但您必须记住实现 equals hashCode,否则您的值将无法从 HashMap 中检索。

关于java - 这个设计有什么问题?覆盖或重载 java.util.HashMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2279907/

相关文章:

java - 使用 Java 检测另一台设备上的端口是否打开

java - 我可以使用 jOOX 查找属性的 xPath 吗?

java - return 语句应该是代码块中的最后一条指令吗?

java - 在java中将字符串列表转换为BigDecimal列表

java - 标签的 widthProperty 何时更新?

java - 为什么用空值实例化变量

math - 何时使用不同的整数类型?

programming-languages - 编程语言中的术语 'object' 和 'instance' 之间有什么区别?

java - 将泛型类型类列表转换为对象列表

java - 如何在 java 8 stream api 中使用 guava Predicates 作为过滤器