&引用;“索引集”&引用;“地图集”;或;SetMap";Java实现

&引用;“索引集”&引用;“地图集”;或;SetMap";Java实现,java,collections,guava,Java,Collections,Guava,我正在寻找一个Java中的Set实现,它提供基于元素属性的查找。以番石榴为例,它可以使用函数构建(预期在所有集合元素中都是唯一的),并提供一种方法find(SearchKey)返回一个元素,函数将返回该元素的键 需要满足的明显的假设: 函数(元素)的结果在集合中元素的整个生命周期内保持不变 函数为所有集合元素提供唯一的结果 原因: 有时需要设置,字段类型不能更改为映射(如JPA实体或第四方代码)。不过,在构建这样一个对象时,人们可以安全地使用自己的Set实现和Map类似的功能 备选方案: 我

我正在寻找一个Java中的
Set
实现,它提供基于元素属性的查找。以番石榴为例,它可以使用
函数构建(预期在所有集合元素中都是唯一的),并提供一种方法
find(SearchKey)
返回一个
元素,函数将返回该元素的

需要满足的明显的假设

  • 函数(元素)
    的结果在集合中
    元素
    的整个生命周期内保持不变
  • 函数为所有集合元素提供唯一的结果
原因:
有时需要
设置
,字段类型不能更改为
映射
(如JPA实体或第四方代码)。不过,在构建这样一个对象时,人们可以安全地使用自己的
Set
实现和
Map
类似的功能

备选方案:

我已经找到了一些替代方案,但没有一个是完美的

  • 没有类似于
    Map
    的功能-对
    find(SearchKey)
    实现使用线性搜索(适用于每个
    实现:)
  • 使用
    TreeSet
    Comparator
    比较
    SearchKeys
    -有点像hack,特别是这不再尊重元素相等性
    “find”方法称为
    天花
    ,需要为查找目的构造人工
    元素
    (uogh…)
  • “等价集”(equivalence set)()——但这并没有实现,似乎也不会实现
如果你想回答你不知道更多的选择——节省时间,不要。这是我已经知道的,我将无法接受你的回答。)

我正在寻找一个用Java实现的集合,它提供基于元素属性的查找

这就是地图的用途,是的,您确实需要构建一个关键对象来表示正在查找的内容

这是Java中最简单、更高效的解决方案,因此虽然它有点令人不快,但我不担心它


顺便说一句:在JRE中,集合通常作为地图上的一个层来实现,这不是理想的IMHO。

如果我正确理解了您的问题,我会想到两个备选方案:

  • 黑客的一种变体:一个带有比较器的
    TreeSet
    ,该比较器将
    YourSearchKey
    YourElement
    进行比较。您可以欺骗类型系统,或者创建一个公共接口
    YourAbstractSearchKey
    。唯一的缺点是:
    • YourSearchKey
      对象可以插入
      集合
      Collections.checkedSet()
      在这一点上可能会有所帮助
    • 搜索结果很可能需要转换到
      YourElement
      。解决方法:在公共界面中定义所有属性
      YourAbstractSearchKey
      ,并让实现
      YourSearchKey
      抛出
      UnsupportedOperationException
  • 类似,但有地图。您不需要向
    YourAbstractSearchKey
    添加额外的属性,因为映射将是
    Map
    。要添加元素,您需要编写
    myMap.put(newElement,newElement)

  • 我一定错过了什么,否则通过
    ForwardingSet
    HashBiMap.keySet()
    很容易。我只关心
    add
    addAll
    ,所有其他的东西都应该不费吹灰之力就能工作。没有单独的测试,我建议使用Guava testlib进行测试。

    您是否确实需要一个对象同时服务于两个角色,或者您是否可以使用集合,然后分别对其进行索引,例如使用
    映射。uniqueIndex
    ?您总是可以创建自己的类型,该类型使用组合和委托的思想从单个对象中公开两组接口。您的理由部分说明了为什么您仍然需要一个
    -它没有解释为什么不能同时拥有这两个集。您的意思是,例如,将
    哈希集
    划分为子类,并具有额外的“索引”这是一张地图,由我自己管理?如果我可以添加一个新类型,我只需添加
    Map
    ,并对这种优雅的方法感到满意。在像JPA beans或第三方数据存储这样的情况下,除了现有的
    Set
    ,您不想/不能添加新字段,因此此解决方案仅适用于某些情况。实际上,我建议使用组合而不是继承。一种新类型,有两个字段(一个map和一个set),其中方法委托给其中一个或两个字段。不幸的是,
    map
    没有一个
    add(Element)
    方法来计算调用者的密钥。此外,我想我已经说过,我仅限于
    Set
    作为一种数据类型,而
    Map
    不实现AFAIK。在我可以更改数据类型的情况下——我完全同意您的意见,sanity和
    映射
    。编写这样一个方法或映射的子类来实现这一点有多复杂?如果您自己获取密钥非常困难,我建议更改您的模型,使其不那么困难。为什么你只限于设置给定集合有完全相同的方法。你说得对<代码>索引集合
    也可以。是否有任何现有的实施?如果没有,我将继续使用我的变通方法ish
    TreeSet
    。我不会建议对库类进行分类。下一次主要JVM升级会遇到麻烦。@VeronicaCornejo很好,虽然子分类是一种选择,但不太可能是最好的选择。最好将此代码添加到包装collection.Woow的内容中。我没有想到这一点。这是非常符合我的一般黑客美联社