Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java集合,在提供引用的同时确保唯一性_Java_Collections_Reference_Unique Key - Fatal编程技术网

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中的树列表?抱歉,您的问题显然是关于
树集的,这个答案是正确的