一尘不染

Java Map为什么不扩展Collection?

java

事实Map<?,?>并非如此,这让我感到惊讶Collection<?>

我认为,如果这样声明,那将是很有意义的:

public interface Map<K,V> extends Collection<Map.Entry<K,V>>

毕竟,Map<K,V>是的集合Map.Entry<K,V>,不是吗?

那么,为什么没有这样一个很好的实现呢?

感谢Cletus提供的最权威的答案,但是我仍然想知道为什么,如果你已经可以查看Map<K,V>as Set<Map.Entries<K,V>>(通过entrySet()),那么它不仅扩展了该接口。

如果a Map是a Collection,则元素是什么?唯一合理的答案是“键值对”

确实interface Map<K,V> extends Set<Map.Entry<K,V>>会很棒!

但这提供了非常有限的(且不是特别有用的)Map抽象。

但是,如果是这种情况,那么为什么要entrySet由接口指定?它必须以某种方式有用(我认为很容易为该职位辩护!)。

你既不能询问给定键所映射的值,也不能在不知道给定键所映射的值的情况下删除给定键的条目。

我并不是说这就是全部Map!它可以并且应该保留所有其他方法(entrySet现在除外,这是多余的)!


阅读 261

收藏
2020-03-17

共1个答案

一尘不染

Map为什么不扩展Collection?
这是设计使然。我们认为映射不是集合,集合也不是映射。因此,Map扩展Collection接口几乎没有意义(反之亦然)。

如果地图是集合,则元素是什么?唯一合理的答案是“键值对”,但这提供了非常有限的(不是特别有用的)映射抽象。你既不能询问给定键所映射的值,也不能在不知道给定键所映射的值的情况下删除给定键的条目。

可以进行收集以扩展Map,但这引发了一个问题:密钥是什么?没有真正令人满意的答案,强迫一个导致不自然的界面。

可以将地图视为键(值,值或对的集合)的集合,这一事实反映在地图上的三个“集合视图操作”(键集,入口集和值)中。虽然原则上可以将列表视为映射到元素的索引的列表,但它具有讨厌的属性,即从列表中删除元素会更改与删除的元素之前的每个元素关联的键。这就是为什么我们在列表上没有地图视图操作的原因。

更新:我认为报价可以回答大多数问题。值得强调的是有关条目集合的部分不是特别有用的抽象。例如:

Set<Map.Entry<String,String>>

将允许:

set.add(entry("hello", "world"));
set.add(entry("hello", "world 2");

(假设有一个entry()创建Map.Entry实例的方法)

Map要求唯一的键,因此会违反此要求。或者,如果你在Set条目上加上唯一键,那么Set从一般意义上说,它实际上不是一个。这是一个Set进一步的限制。

可以说,equals()/hashCode()关系Map.Entry纯粹是关键,但即使这样也有问题。更重要的是,它真的增加了任何价值吗?一旦开始研究极端情况,你可能会发现这种抽象方法崩溃了。

值得注意的HashSet是,实际上将实现为HashMap,而不是相反。这纯粹是实现细节,但仍然很有趣。

entrySet()存在的主要原因是简化遍历,因此你不必遍历键,然后查找键。不要将其作为a Map应该是Set条目(imho)的初步证据。

2020-03-17