Java集合确保唯一性,同时提供参考

问题描述:

我有这样的结构:Java集合确保唯一性,同时提供参考

public class Foo 
{ 
    public int A ; 
    public int B ; 
    public int C ; 
} 

我需要把这些在我结束了不超过这样的方式添加到集合中一个接一个一份A,B和C都相等的副本。我还需要将对象的引用了另一个类,如下所示:

public class Bar 
{ 
    public Foo A ; 
    public Foo B ; 
    public Foo C ; 
} 

我使用TreeSet <Foo>,它努力确保其唯一性试过,但我不能得到一个参考背出一个TreeSet(只是否一个布尔值或者不是/是在集合中),所以我无法将该参考传递给Bar。我尝试使用TreeMap < Foo , Integer >以及ArrayList <Foo>,这样做的目的是确保唯一性并使我能够获取对象的引用,但这会浪费大量时间和内存来维护ArrayListInteger

我需要一种说法“如果这个Foo还没有在集合中,请添加它;否则,请将集合中已有的Foo已经存在,而不是我创建的集合中检查它的存在。 。

(我刚想到我可以做一些像TreeMap < Foo , Foo >这样的事情,而且会做我想做的事情,但它仍然看起来像是浪费,即使它远远不及一个,所以我会继续这个问题在启蒙的希望)

(是的,我也实现Comparable做在树上唯一性检查;这部分工作已经)

+0

为什么你需要它是完全相同的实例?这听起来像是一个危险的想法。但是你可能很容易用你需要的方法扩展'TreeSet'。 – biziclop

+0

所以我添加到'Foo'中的任何其他内容都不会影响唯一性(元数据,基本上)将保留在'Bar'中。 – JAKJ

+0

那么'TreeMap '有什么问题呢? – biziclop

我会使用例如一个TreeMap<Foo, Foo>对象。当您在地图中put新的Foo时,将其指定为关键字和值。这使您可以使用get返回集合中已有的Foo。请注意,您必须自己处理已在地图中的Foo的情况。

+0

我发布了一个答案如下,以做我想要的没有浪费的内存,但在额外的时间成本。我会继续接受这个答案,因为这是相反的方式,浪费一点记忆以换取浪费时间。 这两个答案的工作,取决于时间或记忆是否更重要。 – JAKJ

+0

显然'TreeList'是基于'TreeMap',所以没有什么好浪费的! – Neil

+0

这里没有浪费;一个'TreeMap'每个条目的内存和'TreeSet'一样多。 –

为了确保在Set独特性,你需要重写equals()hashcode(),以便具有相同A,B,C的Foo的两个实例是.equals()

理想的情况下,任何你放在一个集应该是一成不变的(即你的三个整数应finaldocumentation:。

如果使用可变对象作为设定 元素

大,一定要小心的如果 对象的值以影响equals比较而 的对象是在该组的元素的方式变化没有被指定的一组行为。

不幸的是,Set没有提供任何方法让您获取实际实例 - 您需要使用Map或另一个集合,因为您已经尝试过。

更新另一种方法是创建基于JDK source code TreeSet中的自己的修改版本添加一个方法来获取你需要的实例(扩展标准TreeSet的不会做你所需要的,因为相关领域是private,除非您使用反射来访问它们)。

由尼尔·科菲在Sorted collection in Java一个解决方案给了我所需要的,这是使用ArrayList <Foo>始终做Collections . binarySearch获得或者已经在列表中的元素的索引,或者该元素应该被插入到列表中的点。

这样在O(log n)时间像树一样维护一个不断排序的列表,但允许同时检索现有实例。不幸的是,它有O(n)个插入时间,但在这种情况下这不是世界的尽头,尽管它仍然不是最理想的。

显然TreeList是基于TreeMap从而使这种方法是多余的,但我认为我只是评论它的完整性。

如果TreeList存在Foo对象的副本(例如,通过contains返回)然后可以检索使用tailSetfirst方法副本。

+0

Java没有我能找到的TreeList。我认为你的意思是Commons API中的那个? – JAKJ

+0

对不起,你的问题显然是一个'TreeSet',这个答案也应该是一个'TreeSet'。我不知道我是如何设法编写'TreeList'的。你想让我编辑我的答案吗? – Neil