Java 树集没有添加所有元素?

Java 树集没有添加所有元素?,java,collections,tree,set,treeset,Java,Collections,Tree,Set,Treeset,我一直在研究不同Java集合类型的速度,发现了一些奇怪的东西。我正在将1000000个对象从静态数组添加到不同的集合类型,并返回所需的时间。这部分代码运行良好 在进一步的调查中,我注意到TreeSet并没有接收到1000000个对象中的所有对象,并且每次接收的数量都不同。下面是将对象从数组传输到树集的方法: public int treeSet(int num) { Date before = new Date(); for(int i=0; i&l

我一直在研究不同Java集合类型的速度,发现了一些奇怪的东西。我正在将1000000个对象从静态数组添加到不同的集合类型,并返回所需的时间。这部分代码运行良好

在进一步的调查中,我注意到
TreeSet
并没有接收到1000000个对象中的所有对象,并且每次接收的数量都不同。下面是将对象从数组传输到
树集的方法:

    public int treeSet(int num)
    {
       Date before = new Date();

       for(int i=0; i<num; i++) 
       {
           treeSet.add(personsArray[i]);
       }

       Date after = new Date();
       return (int) (after.getTime() - before.getTime());
    }
其输出为:

    Tree set with 1,000,000 objects--1192
    Tree set contains 975741 elements

我希望有人能向我解释为什么
TreeSet
没有接收到所有的对象,以及为什么它接收到的对象数量不一致。

请确保
People
类上的
compareTo()
方法得到正确实现。
Comparable
javadoc声明如下:

强烈建议(尽管不是必需的)使用自然排序 与平等相一致。这是因为排序集(和排序贴图) 如果没有显式的比较器,当它们与 其自然顺序与equals不一致的元素(或键)。在里面 特别是,这样的排序集(或排序图)违反了总合同 对于集合(或映射),定义为
等于

方法

例如,如果添加两个键
a
b
,则
(!a.equals(b)&&a.compareTo(b)==0)
到排序后的 不使用显式比较器的设置,第二个
add
操作返回false(并且排序集的大小不会增加) 因为
a
b
与排序集的 透视图


我可以满怀信心地说,您正在向
树集添加重复项。如果您不相信我,只需将数字添加到您的
树集
,确保数字从
1
1000000
,您就会看到您将得到您所期望的结果

一旦你澄清了你的疑问,那么让我们试着把你的人分类

将以下内容添加到人员类:

int id;    //ensure that every people object you create has different id. e.g. 1 to 10m;

@override
public boolean equals(Object o){
  if(this.getClass()!=o.getClass()) return false;
  else return (People (o)).id==this.id;
}

@override
public int hashCode(){
 return id;
}
现在开始向集合中添加内容。:)


注意此代码只是创建不同人员类的简单方法的一个示例。使用treeSet等进行一些测试是一种很好的方法,但对于实际问题不建议使用这种方法

您几乎肯定会生成重复的Person对象

在你的文章中,你说每个人都是从包含“数百”个名字和年龄的文本文件中随机生成的,包括性别、名字和姓氏。假设性有两种可能,名字和姓氏各有300种,年龄有100种。总共有18000000个可能是独一无二的人

让我们进一步假设
equals()
在这个对象上得到了正确的实现,也就是说,它正确地检查了所有这些字段

在18000000个可能性中,你使用随机特征生成了1000000个独特的人

直觉上,你可能认为有一个“极小”的复制机会,但有复制的概率实际上是1.0减去ε。这就是所谓的“生日悖论”,有时甚至是“生日悖论”

如该页所示,任意两种选择之间发生冲突的概率约为

1-((d-1)/d)^n(n-1)/2

其中d是域中的值的数量,n是所做选择的数量。我不完全确定,但对于d=18000000和n=1000000的值,我认为这大约是1.0-1E-323。(编辑:正确的值大约是
1.0-2.84E-12294
。这非常接近。)

这种选择中的预期碰撞次数由以下公式给出:

n-d+d*((d-1)/d)^n

如果d=18000000,n=1000000,则计算得出约27000。也就是说,平均你会遇到27000次碰撞。这与树集合中“缺失”元素的数量非常接近,这就是冲突如何表现出来的。我承认我选择的数字与你看到的非常接近,但我的假设和结果完全可信


您需要重新考虑生成存储到集合中的数据的方式。

添加到
树集合中的项目相等的几率是多少<代码>树集
不允许重复。这些对象完全相同的几率很小。对象是人,随机生成性别、名字、姓氏和年龄。这些名称取自一个包含数百个不同名称的.txt文件
to
if(!treeSet.add(personsArray[i]){System.out.println(“找到冲突”);}
。非常感谢您的帮助。结果是添加了重复项(我没有完全理解compareTo()方法及其意义)。树集不太可能有bug。因此,您的程序或推理可能存在错误。所以你真的应该发布
Person
类的代码。如果有人对我如何计算概率感兴趣:
int id;    //ensure that every people object you create has different id. e.g. 1 to 10m;

@override
public boolean equals(Object o){
  if(this.getClass()!=o.getClass()) return false;
  else return (People (o)).id==this.id;
}

@override
public int hashCode(){
 return id;
}