当前位置: 首页 > 面试题库 >

Java Map为什么不扩展Collection?

澹台宾白
2023-03-14
问题内容

事实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现在除外,这是多余的)!


问题答案:

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)的初步证据。



 类似资料:
  • 问题内容: 为什么接口不扩展接口?不是键值对的集合吗? 问题答案: 集合假定一个值的元素。映射假定键/值对的条目。他们本来可以重新使用相同的通用接口,但是它们实现的某些方法不兼容,例如 您可以将Map建模为条目的集合,这就是这样做的。 有一些共同的方法。,,,但这些都不太可能有多少价值作为一个独立的接口。(可以再次使用)

  • 问题内容: 创建数组时,无法更改其大小;它是固定的。好的,看起来不错,我们可以创建一个新的更大的数组并逐个复制值,这有点慢。它的技术背景是什么? 问题答案: 这个问题没有提到语言,因此我将选择基于“ C”的数组作为答案。 数组被分配为单个内存块。增长数组是有问题的,因为正确执行此操作的唯一方法是在最后增长它。为了增加大小N,在数组的末尾必须在下一个分配的地址之前至少有N个空闲字节。 要支持这种类型

  • 问题内容: 我想知道为什么在Java语言中a 不能扩展。 我不是在谈论一个延伸的(这不能做,因为Java没有多重继承,而Š隐含延长),但一类的以只添加额外的方法,而不是额外的枚举值。 就像是: 要这样使用: 因此,有人可以对此限制提供理由(或将我指向正确的JLS部分)吗? 问题答案: 我认为 他们这样做 的答案来自以下问题: 在您的示例中,如何实例化MyClass?用户永远不会(通过)显式实例化枚

  • 如果我编写了ToIntFunction接口,我希望在接口中编码这样一个事实,即它只是一个返回原始int的函数,如下所示: 我想知道,Java8 API设计者选择将原始的替代方案与函数完全分离,是不是有一个令人信服的原因?是否有证据显示他们曾考虑这样做,并决定不这样做?我想类似的问题至少也会出现在其他一些“特殊”功能接口上,比如Consumer(可能是function )和Supplier(func

  • 我知道一些关于AbstractQueuedSynchronizer的详细信息。它是一个用于创建依赖于状态的类或同步器的框架。但我不理解在ThreadPoolExecutor的Worker中扩展这个类的意义。 由Worker类的签名可以推断出以下内容: > 提交新的可运行/可调用任务时,将创建一个新的工作对象。 Worker的新对象可以被视为新线程。 方法将添加新的worker(或只是一个任务)并在

  • 扩展是可定制化浏览体验的小程序,它们使用户可以根据个人需要或者偏好定制 Chrome 的功能和行为。它们基于 Web 技术(例如 HTML,JavaScript 和 CSS)构建。 扩展必须满足狭义定义且易于理解的单一目的(译者注:功能简单易懂化)。一个扩展可以包括多个组件和一系列功能,只要所有的内容都有助于实现共同的目标。 用户交互界面应尽量小且有意图。他们的范围从简单的图标,如右侧显示的 Go