假设您有以下代码:
Map<Foo, Bar> map = new HashMap<Foo, Bar>();
Foo foo = new Foo();
Bar bar = new Bar();
map.put(foo, bar);
Bar barReturned = map.get(foo);
Java是否需要barReturned == bar
?也就是说,Java 是否需要 barReturned
与<{1}}相同的实例?如果没有,预期会有什么语义?
Javadoc表示bar
必须为真,但我不是百分百确定:
barReturned == bar
返回指定键映射到的值,如果此映射不包含键的映射,则返回
V get(Object key)
。更正式地说,如果此地图包含从关键
null
到值k
的映射,使得v
,则此方法返回(key==null ? k==null : key.equals(k))
;否则返回v
。 (最多可以有一个这样的映射。)如果此映射允许
null
值,则返回值null不会必须表示映射不包含该键的映射;地图也可能明确地将密钥映射到null
。 containsKey操作可用于区分这两种情况。参数:
null
- 要返回其关联值的键返回:
指定密钥映射的值 ,如果此地图不包含密钥映射,则为
key
(强调我的)
编辑:我了解与标准库捆绑在一起的null
实现遵循Map
语义。我想知道的是,根据文档,此行为是否必需。例如,如果我编写自己的实现barReturned == bar
的类,我是否还必须遵守这些语义?
答案 0 :(得分:4)
如果你问你是否可以打破这种关系,我认为答案是肯定的。例如,如果您正在实现一个像持久性缓存一样的Map,那么如果不在一段时间内使用,则可以将特定值写入磁盘,然后再重新加载。在那种情况下你不会有参考平等,但那没关系。显然,你想要记录任何与标准行为的偏差,但我认为这不符合合理使用地图的范围。
答案 1 :(得分:1)
当然,它将是相同的实例。否则Map
将毫无用处。
但是,唯一的例外是多线程应用程序,其他线程可以在您对put
和get
的调用之间为同一个键添加任意值。
编辑正如Adam在评论中指出的,他有一些特殊情况,他的Map实现可以重新创建传入的对象并使用他们的副本。意义上的副本original.equals(copy)
为真,original == copy
为假。在这种情况下,我认为Map可以存储副本而不是原始副本。
答案 2 :(得分:1)
如果您将javadoc中使用的术语值解释为地图中对象的引用,则意味着您始终需要返回与您相同的引用放入地图,你就会有==平等。然后,它变得更加成为文档中使用的术语值定义的问题。
答案 3 :(得分:1)
javadoc并没有明确地说明(或限制)你放在地图中的值在物理上等于放入它的那些值。 所以我敢说,没有100%的保证,它必须如此。 你可能会认为:
Map<Foo,Bar> map = new HashMap<Foo,Bar>();
Foo foo = new Foo();
Bar bar = new Bar();
map.put(foo, bar);
System.out.println( bar.equals( map.get(foo) ) ); // ==> Should be guaranteed
System.out.println( bar == map.get(foo) ); // ==> no guarantee
理论上,您可以创建在不同JVM上共享和同步的集群Map实现,在这种情况下,获取相同的物理实例是不可能的(或者至少非常困难)。
我的意见是,在您的实施中,您应该保证bar.equals( map.get(foo) )
,但不是必须bar == map.get(foo)
。
但是,只要您清楚地记录并说明上述两种情况都不能得到保证,您就可以使用Map实现做您想做的事情。 ;)
答案 4 :(得分:1)
如果您正在实现自己的Map版本,那么您不需要返回相同的对象实例。文档和语言中没有任何内容要求您的实现返回相同的对象实例。
当且仅当代码中存在某些库或其他部分时,您的代码可能会中断(无理由,但通常是合理的)假设返回值将是同一个对象实例。在这种情况下,好吧,只是不要将Map的实现传递给该代码。
Patient: Doctor, it hurts when I do this
Doctor: Well, don't do that
答案 5 :(得分:1)
注意它表示键映射到的“值”,而不是“引用”或“实例”。当你听到“值”时,它会建议Object.equals()语义。你无需担心。
答案 6 :(得分:0)
class Foo{
}
class Bar{
}
public class MapDemo {
public static void main(String[] args) {
Map<Foo,Bar> map = new HashMap<Foo,Bar>();
Foo foo = new Foo();
Bar bar = new Bar();
map.put(foo, bar);
System.out.println(bar == map.get(foo));
}
}
返回 true
HashMap
实现了Map
,但没有任何内容可以写出来。
/**
137 * Returns the value of the mapping with the specified key.
138 *
139 * @param key
140 * the key.
141 * @return the value of the mapping with the specified key, or {@code null}
142 * if no mapping for the specified key is found.
143 */
但几乎每个实现都这样做,我的意思是它保持相同的Object