Java集合,在提供引用的同时确保唯一性
我有一个这样的结构:Java集合,在提供引用的同时确保唯一性,java,collections,reference,unique-key,Java,Collections,Reference,Unique Key,我有一个这样的结构: public class Foo { public int A ; public int B ; public int C ; } public class Bar { public Foo A ; public Foo B ; public Foo C ; } 我需要一个接一个地将它们添加到一个集合中,这样我就不会得到多个副本,其中a、B和C都相等。我还需要引用另一个类的对象,如下所示: public class Foo
public class Foo
{
public int A ;
public int B ;
public int C ;
}
public class Bar
{
public Foo A ;
public Foo B ;
public Foo C ;
}
我需要一个接一个地将它们添加到一个集合中,这样我就不会得到多个副本,其中a、B和C都相等。我还需要引用另一个类的对象,如下所示:
public class Foo
{
public int A ;
public int B ;
public int C ;
}
public class Bar
{
public Foo A ;
public Foo B ;
public Foo C ;
}
我尝试使用TreeSet
,这可以确保唯一性,但我无法从TreeSet中获取引用(只能获取该引用是否在集合中的布尔值),因此我无法将该引用传递到Bar
。我尝试使用TreeMap
和ArrayList
,这可以确保唯一性并允许我获取对对象的引用,但是维护ArrayList
和Integer
会浪费大量的时间和内存
我需要一种方式来表示“如果此Foo
尚未在集合中,请添加它;否则,请将已在集合中的Foo
提供给我,而不是我为检查其是否在集合中而创建的。”
(我刚刚想到,我可以做一些类似于TreeMap
的事情,这会做我想做的事情,但这似乎仍然是一种浪费,尽管它远不及一种浪费,所以我将继续问这个问题,希望能有所启发。)
(是的,我确实实现了
Comparable
来在树中进行唯一性检查;这一部分已经起作用了。)为了确保集中的唯一性,您需要超越equals()
和hashcode()
,以便具有相同a、B、C的两个Foo实例是equals()
理想情况下,您在集合中输入的任何内容都应该是不可变的(即,您的三个整数应该是final
)
如果将可变对象用作集合,则必须非常小心
元素。如果
对象的更改方式会影响equals比较,而
对象是集合中的一个元素
不幸的是,Set
没有提供任何方法来获取实际实例-您需要一个Map
或其他集合,就像您已经尝试过的那样
更新另一种方法是基于JDK创建您自己的修改版本的TreeSet,以添加一个方法来获取您需要的实例(扩展标准TreeSet不会做您需要的事情,因为相关字段是私有的
,除非您使用反射来访问它们).我会使用例如TreeMap
对象。当您在地图中放置一个新的Foo
时,将其指定为键和值。这允许您使用get
返回集合中已经存在的Foo
对象。请注意,您必须自己处理Foo
已经存在于地图中的情况。 Neil Coffey在中的一个解决方案提供了我所需要的,即使用ArrayList
,并始终执行集合。binarySearch
以获取列表中已存在元素的索引,或元素应插入列表的点
它像树一样在O(logn)时间维护一个不断排序的列表,但允许同时检索现有实例插入时间,但在这种情况下这并不是世界末日,尽管它仍然是次优的。显然树列表基于树映射
,因此这种方法是多余的,但为了完整性,我想我还是对它进行评论
如果Foo
对象的副本存在于TreeList
中(例如,返回的包含)然后,您可以使用tailSet
和first
方法检索副本。为什么需要完全相同的实例?这听起来是一个危险的想法。但是您可以使用所需的方法轻松地扩展TreeSet
。这样,我添加到Foo
中的任何其他内容都不会产生独特的效果ness(基本上是元数据)将在Bar
中维护。那么TreeMap
有什么问题吗?Bar
类包含Foo
的实例,我首先必须检查其存在性,然后将其存储在Bar
中。你刚才所说的毫无意义。(没关系,我明白你现在所说的,但这对我来说不起作用,因为同一个Foo
可能在多个Bar
中,我必须对Bar
中的Foo
进行额外的平等性检查,以确定哪一个是我的参考。)我在下面贴了一个答案,是关于如何在不浪费内存的情况下做我想做的事情,但要付出额外的时间。我将继续接受这个答案,因为反过来说,浪费一点内存可以换取不浪费时间。这两个答案都有效,这取决于时间或内存是否更重要。显然是树列表
基于树映射
所以没有什么可浪费的!这里没有浪费;树映射
每个条目占用的内存与树集
完全一样。我在这里又做了一次。我的意思是说树映射
当然是基于树映射
的,因此使用树映射
会消耗同样的内存内存量(虽然我不完全相信@LouisWasserman的说法,它完全一样…)对不起,这是错误的。TreeSet
比TreeMap
多占用几个字节(基本上,TreeSet
只是)由于您实际上没有在树映射中复制对象,您只是存储了两个引用,因此数学计算是正确的。您可能会发现这很有用。Java没有我可以找到的树列表。我假设您是指Commons API中的树列表?抱歉,您的问题显然是关于树集的,这个答案是正确的