代码之家  ›  专栏  ›  技术社区  ›  gstackoverflow

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

  •  24
  • gstackoverflow  · 技术社区  · 10 年前

    我知道如果我有元素,我想 List / Set / Map 使用此元素,我可以调用:

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

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

    是否有类似的方法来获得可变集合?

    2 回复  |  直到 10 年前
        1
  •  17
  •   fgb    10 年前

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

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

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

    Sets.newHashSet(...)
    Lists.newArrayList(...)
    Maps.newHashMap(ImmutableMap.of(...))
    
        2
  •  12
  •   fdreger    2 年前
    1. 这样的API退出是没有意义的,因为您可以始终使用获取集合的构造函数( new ArrayList(Collections.singleton(whatever)) )

    2. 如果它存在,那将是有害的。没有合理的API允许您选择新集合的实现(例如。 LinkedList 与。 ArrayList )或附加参数(如初始大小)。

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

    **附录(几年后,我仍然对这个答案投反对票,所以解释中可能有些不清楚)**

    标准库中的单例集合不是“真实的”——它们是通过存储单个引用的单个属性实现的;没有办法把它们做大。它们是“赝品”;“存根”。

    那么,为什么要有它们呢?这是一个(次要的)性能优化:要创建一个不可变的单例集合,只需要一个分配,而所有“真实”集合至少需要两个。即:即使我们只在 阵列列表 ,实现需要分配一个额外的数组。即使我们在 链表 ,它需要分配 Node 。等等。没办法。

    通常,一个额外的分配/对象不是问题,但在一些性能关键的地方,这会增加。因此,标准库为我们提供了一种“为不需要完整集合功能的性能关键场所创建一个额外廉价的真实集合替代品”的方法

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

    这种困惑——很可能是因为有人可以将“单例”方法解释为“算法优化”,而不是“更少的类型和更好的代码优化”。如果这是您的观点,那么标准库确实可以为“可变单态”提供一些糖。这并不是因为我们会节省一些(字面上是几个字符,甚至不是十个),同时会损失很多-想想创建不同实现的重写(linkedList vs arrayList)或参数化现有的实现(我如何创建一个单变量 阵列列表 为16个对象预先分配空间?)