是否有模拟 Collections.singleton() / Collections.singletonList() / Collections.singletonMap() 来获取可变集合?

2022-09-01 23:27:15

我知道我是否有元素,我想得到//与这个元素,我可以调用:ListSetMap

Collections.singleton() / Collections.singletonList() / Collections.singletonMap()

在这种情况下,我得到了不可变的集合(我无法将元素添加/删除到集合中)。

是否有模拟来获得可变集合?


答案 1

使用标准库,您可以使用:

new ArrayList<...>(Arrays.asList(...)))
new HashSet<...>(Arrays.asList(...)))

它们可以采用任意数量的元素作为参数。像番石榴这样的图书馆有稍微方便的方法:

Sets.newHashSet(...)
Lists.newArrayList(...)
Maps.newHashMap(ImmutableMap.of(...))

答案 2
  1. 这样的 API 退出是没有意义的,因为您始终可以使用采用集合 (new ArrayList(Collections.singleton(whatever)))

  2. 如果它存在,那将是有害的。没有一个健全的API可以让你选择新集合的实现(例如。 vs. ) 或附加参数(如初始大小)。LinkedListArrayList

单例集合只是非常精简的适配器,用于将单个对象传递给需要集合的 API。让它们可变将完全违背这一点。

**附录(因为,多年后,我仍然对这个答案投了反对票,所以也许从解释中不清楚某些事情)**

标准库中的单例集合不是“真实的” - 它们是使用存储单个引用的单个属性实现的;没有办法让它们变得更大。他们是“假货”;“存根”。

那么为什么要有它们呢?这是一个(次要的)性能优化:要创建不可变的单例集合 - 只需要一个分配,而所有“真实”集合至少需要两个。即:即使我们只在 中存储单个对象,实现也需要分配一个额外的数组。即使我们将单个对象存储在 中,它也需要分配一个 .等等。没有办法绕过它。ArrayListLinkedListNode

通常,单个额外的分配/对象不是问题,但在某些性能关键的地方 - 这将加起来。因此,标准库为我们提供了一种方法,可以“为不需要完整馆藏功能的性能关键位置创建一个额外的廉价替代物。

从单一实例集合 API 返回可变集合将使 API 存在的唯一原因无效。

混淆 - 可能是因为有人可以将“单例”方法解释为“算法优化”,而不是“更少的类型和更好的代码优化”。如果这是你的观点,那么标准库确实可以为“可变单例”提供一些糖。它不会,因为我们会节省花生(字面上是几个字符,甚至不是十个),而损失很大 - 考虑创建不同实现的覆盖(linkedList与数组列表)或参数化现有的内涵(我如何创建一个单例可变的预分配16个对象的空间?ArrayList