pol*_*nts 142 java oop collections
我对这Map<?,?>不是一个事实感到惊讶Collection<?>.
我认为如果宣布这样的话会有很多意义:
public interface Map<K,V> extends Collection<Map.Entry<K,V>>
Run Code Online (Sandbox Code Playgroud)
毕竟,一个Map<K,V>是集合Map.Entry<K,V>,不是吗?
那么为什么没有这样实现呢?
感谢Cletus提供了最权威的答案,但我仍然想知道为什么,如果您已经可以查看Map<K,V>as Set<Map.Entries<K,V>>(via entrySet()),它不仅仅是扩展该界面.
如果a
Map是aCollection,那么元素是什么?唯一合理的答案是"键值对"
确切地说,interface Map<K,V> extends Set<Map.Entry<K,V>>会很棒!
但这提供了非常有限(并且不是特别有用)的
Map抽象.
但如果是这种情况那么为什么entrySet界面指定?它必须以某种方式有用(我认为这个位置很容易争论!).
您不能询问给定键映射到的值,也不能删除给定键的条目而不知道它映射到的值.
我不是说这就是它的全部内容Map!它可以而且应该保留所有其他方法(除了entrySet现在多余的方法)!
cle*_*tus 121
来自Java Collections API Design FAQ:
为什么没有Map扩展Collection?
这是设计的.我们认为映射不是集合,集合不是映射.因此,Map扩展Collection接口(反之亦然)毫无意义.
如果Map是Collection,那么元素是什么?唯一合理的答案是"键值对",但这提供了非常有限(并且不是特别有用)的Map抽象.您不能询问给定键映射到的值,也不能删除给定键的条目而不知道它映射到的值.
收集可以扩展Map,但这提出了一个问题:关键是什么?没有真正令人满意的答案,强迫一个人导致不自然的界面.
地图可以被视为集合(键,值或对),这一事实反映在地图上的三个"集合视图操作"(keySet,entrySet和values)中.虽然原则上可以将List视为映射索引到元素的映射,但这具有令人讨厌的属性,即从列表中删除元素会更改与删除元素之前的每个元素关联的键.这就是为什么我们没有列表上的地图视图操作.
更新:我认为报价回答了大部分问题.值得强调的是关于一组条目不是特别有用的抽象的部分.例如:
Set<Map.Entry<String,String>>
Run Code Online (Sandbox Code Playgroud)
会允许:
set.add(entry("hello", "world"));
set.add(entry("hello", "world 2");
Run Code Online (Sandbox Code Playgroud)
(假设entry()创建Map.Entry实例的方法)
Maps需要唯一的密钥,所以这会违反这一点.或者如果你对一个Set条目强加了唯一的键,那么它Set通常不是一般意义上的.这是一个Set进一步的限制.
可以说你可以说equals()/ hashCode()关系Map.Entry纯粹是关键,但即便有问题.更重要的是,它真的增加了任何价值吗?一旦开始查看角落案例,您可能会发现这种抽象分解.
值得注意的是,HashSet它实际上是以一种HashMap方式实现的,而不是相反.这纯粹是一个实现细节,但仍然很有趣.
entrySet()存在的主要原因是简化遍历,因此您不必遍历密钥,然后查找密钥.不要把它作为表面证据表明a Map应该是Set条目(imho).
ewe*_*nli 10
我想这就是为什么是主观的.
在C#中,我认为Dictionary扩展或至少实现了一个集合:
public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>,
ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>,
IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback
Run Code Online (Sandbox Code Playgroud)
在Pharo Smalltak中:
Collection subclass: #Set
Set subclass: #Dictionary
Run Code Online (Sandbox Code Playgroud)
但是某些方法存在不对称性.例如,collect:将获取关联(相当于一个条目),同时do:取值.它们提供了另一种keysAndValuesDo:通过条目迭代字典的方法.Add:采取关联,但remove:已被"压制":
remove: anObject
self shouldNotImplement
Run Code Online (Sandbox Code Playgroud)
所以它确实可行,但导致了关于类层次结构的一些其他问题.
更好的是主观的.
Jer*_*fin 10
虽然你已经得到了许多直接覆盖你的问题的答案,但我认为退一步可能是有用的,并且更一般地看一下这个问题.也就是说,不要特别注意如何编写Java库,并查看为什么以这种方式编写它.
这里的问题是继承只模拟一种类型的共性.如果你挑选出两件看起来像"像集合一样"的东西,你可能会挑选出他们共同拥有的8或10件东西.如果你选择一对不同的"收藏式"东西,它们也会有8或10个共同点 - 但它们与第一对不会是8或10个相同的东西.
如果你看一下十几个不同的"类似收藏"的东西,几乎每一个都可能有至少一个共同的8或10个特征 - 但如果你看看每个人共享的东西是什么他们中间几乎没有任何东西.
这是继承(尤其是单继承)不能很好地建模的情况.它们之间没有干净的分界线,哪些是真正的集合,哪些不是 - 但是如果你想要定义一个有意义的Collection类,你就会把它们中的一些留下来.如果只留下一些,你的Collection类只能提供相当稀疏的接口.如果你留下更多,你将能够给它一个更丰富的界面.
有些人还可以选择基本上说:"这种类型的集合支持操作X,但是你不允许使用它,通过从定义X的基类派生,但尝试使用派生类'X失败(例如, ,通过抛出异常).
这仍然存在一个问题:几乎无论你遗漏哪个以及你放弃了什么,你都必须在哪些类和哪些类之间划清界限.无论你在哪里绘制这条线,你都会在一些非常相似的东西之间留下一个清晰的,相当人为的区分.
| 归档时间: |
|
| 查看次数: |
39875 次 |
| 最近记录: |