我的应用程序中有两种对象,其中一种对象恰好有一个对应的另一种对象。
跟踪这种关系的明显选择是Map<type1, type2>
,例如 HashMap。但不知何故,我很怀疑。我可以在 Map 中使用一个对象作为键,传递它,让它也放在另一个集合中,并随时从 Map 中检索它的伙伴吗?
创建对象后,我传递的只是一个标识符,对吗?所以那里可能没有问题。如果我序列化和反序列化密钥怎么办?
还有其他注意事项吗?我是否应该使用其他东西来关联对象对,例如我自己生成的数字?
我的应用程序中有两种对象,其中一种对象恰好有一个对应的另一种对象。
跟踪这种关系的明显选择是Map<type1, type2>
,例如 HashMap。但不知何故,我很怀疑。我可以在 Map 中使用一个对象作为键,传递它,让它也放在另一个集合中,并随时从 Map 中检索它的伙伴吗?
创建对象后,我传递的只是一个标识符,对吗?所以那里可能没有问题。如果我序列化和反序列化密钥怎么办?
还有其他注意事项吗?我是否应该使用其他东西来关联对象对,例如我自己生成的数字?
.equals()
和.hashCode()
正确.hashCode()
HashMap
都应该是不可变的。这将自动确保 2. 始终为真。我的应用程序中有两种对象,其中一种对象恰好有一个对应的另一种对象。
这听起来确实像一个有关系,因此可以使用一个简单的属性来实现。
这取决于您选择的地图的实现:
HashMap使用equals()和hashCode()。默认情况下(在对象中),这些基于对象标识,除非您序列化/反序列化,否则它将正常工作。根据对象的内容正确实现 equals() 和 hashCode() 不会有任何问题,只要在它是哈希映射中的键时不对其进行修改。
TreeMap使用compareTo()。没有默认实现,因此您需要提供一个。与上面实现 hashCode() 和 equals() 的限制相同。
您可以使用标准 Map,但这样做会在 Map 中保留对对象的强引用。如果您的对象在另一个结构中被引用,并且您需要 Map 只是将它们链接在一起,请考虑使用 WeakHashMap。
顺便说一句,除非您必须将对象的多个实例视为相等,否则您不必覆盖 equals 和 hashCode...
我可以在 Map 中使用一个对象作为键,传递它,让它也放在另一个集合中,并随时从 Map 中检索它的伙伴吗?
是的,这里完全没有问题。
创建对象后,我传递的只是一个标识符,对吗?所以那里可能没有问题。如果我序列化和反序列化密钥怎么办?
没错,您只是在传递一个引用——它们都将指向同一个实际对象。如果您序列化或反序列化对象,则会创建一个新对象。但是,如果您的对象正确实现了 equals 和 hashCode,您应该仍然能够使用新的反序列化对象从地图中检索项目。
还有其他注意事项吗?我是否应该使用其他东西来关联对象对,例如我自己生成的数字?
至于注意事项,是的,当对象在 Map 中时,您不能更改任何会导致对象的 hashCode 更改的内容。
任何对象都可以是映射键。这里重要的是确保为将用作映射键的任何对象覆盖 .equals() 和 .hashCode()。
这样做的原因是,如果不这样做,equals 将被理解为对象相等,并且您能够找到“相等”映射键的唯一方法是拥有原始对象本身的句柄。
您覆盖哈希码是因为它需要与 equals 一致。这是为了使您定义为 equals 的对象具有相同的哈希值。
故障点是 hashcode 和 equals 函数。如果它们不能产生一致且正确的返回值,则 Map 的行为会很奇怪。Effective Java有一个完整的章节,强烈推荐。
您可能会考虑 Google Collection 的BiMap。