我编写了一个可以随机获得容器内对象的容器。这个容器包括两个关键方法:一个是用来完全随机获得容器内对象,叫做AllRandomGet();另一个是传入一个排除数组,容器会自动从排除列表外的对象中随机选取对象返回,叫做randomGetButExcept(Classroom[] except)。但是编出来后发现第二个方法不好用。用循环10000次试验,发现第二个方法会显著减少得到排除列表中对象的次数,但是却不能完全阻止(按道理来说排除列表中元素不该得到),不知道是怎么回事。以下附代码:
//classroom.java 这个类是容器中的基本元素,这里为了简化,只有一个元素id
public class Classroom {
private int id; public Classroom(int id) {
this.id = id;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public boolean equals(Object obj) { //根据id是否相同来判断是否相等
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Classroom other = (Classroom) obj;
if (this.id != other.id) {
return false;
}
return true;
}
}
//ClassroomContainer.java 装classroom对象的容器类
public class ClassroomContainer {
private Classroom[] classroom; //装存classroom对象的数组
private int currentCapacity; //当前容器的容量
private int currentIndex; //当前容器装了多少对象-1,因为存的是下标
private int increase=10; //每次容量不够时的增长量
public void put(Classroom classroom){ //将一个classroom对象装入容器
if(currentIndex>=currentCapacity-1) //容量不够则增加容量
increaseLength();
this.classroom[currentIndex++]=classroom;
}
public Classroom AllRandomGet(){ //随机获取容器中一个对象
int i=(int)((new java.util.Random().nextFloat())*currentIndex); //产生在[0,currentIndex)区间的随机整数
return classroom[i]; //返回产生随机数对应的对象
}
public Classroom randomGetButExcept(Classroom[] except){ //随机获取容器中除了排除数组中对象的其他对象
ClassroomContainer cc=new ClassroomContainer();
for(int i=0;i<currentIndex;i++){ //遍历当前容器的对象
for(int j=0;j<except.length;j++){ //遍历排除数组中的对象
if(except[j].equals(classroom[i])) //若相等则不予处理
continue;
else{
cc.put(classroom[i]); //若对象不在排除列表中则放入一个新容器
}
}
} //新容器中只放不在排除列表中对象
return cc.AllRandomGet(); //新容器中随机返回一个对象
}//以下为相应的其他方法
public ClassroomContainer(){
this(20);
}
public ClassroomContainer(int capacity){
classroom=new Classroom[capacity];
this.currentCapacity=capacity;
this.currentIndex=0;
}
private void increaseLength(){ //增长长度
increaseLength(increase);
}
private void increaseLength(int increase){
Classroom[] newClassroom=new Classroom[currentCapacity+increase];
for(int i=0;i<=currentIndex;i++)
newClassroom[i]=classroom[i];
classroom=newClassroom;
currentCapacity+=increase;
System.out.println("Capacity Increased");
}//main方法
public static void main(String[] args){
Classroom[] c=new Classroom[10];
Classroom[] forbid=new Classroom[3];
int[] count=new int[10]; //对id 0-9 的每个对象取得次数计数器
for(int i=0;i<10;i++)
count[i]=0;
for(int i=0;i<10;i++){
c[i]=new Classroom(i); //定义id号0-9的classroom对象
}
forbid[0]=c[1];
forbid[1]=c[2];
forbid[2]=c[3]; //将id为1,2,3的对象加入排除数组
ClassroomContainer cc=new ClassroomContainer();
for(int i=0;i<10;i++)
cc.put(c[i]); //将id 0-9的对像加入容器
for(int i=0;i<10000;i++){
count[cc.randomGetButExcept(forbid).getId()]++; //循环10000次,并对每个对象取得次数进行计数
}
for(int i=0;i<10;i++){
System.out.println(count[i]); //将计数结果打印出来
}
}
}本来按照想法,结果中对应id号1,2,3的计数器应该为0,即count[1-3]。可是结果完全出乎意料。以下是在netbeans中运行生成结果:
1112
760
768
725
1078
1157
1093
1069
1144
1094可以看到,count[1-3]确实是大幅度减小了,但是却不是预想的0。为了证明随机取得的随机性,用AllRandomGet()(完全随机获得)方法再做一次10000个循环的试验,结果如下:
1007
993
1012
1040
996
993
995
999
994
971
可见,结果基本上是符合随机的。所以结果我就觉得很奇怪了,我设计的方法应该是完全阻止而不是减少获取到排除数组中对象的次数。但是,结果并不完全符合想象,大家帮我看看这是怎么回事呢?ps:一般来说的覆盖equals()就要覆盖hashCode()对这里并不适用,我覆盖了hashCode()结果还是如上面一样,只是大幅度消减,而不是阻止。
//classroom.java 这个类是容器中的基本元素,这里为了简化,只有一个元素id
public class Classroom {
private int id; public Classroom(int id) {
this.id = id;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public boolean equals(Object obj) { //根据id是否相同来判断是否相等
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Classroom other = (Classroom) obj;
if (this.id != other.id) {
return false;
}
return true;
}
}
//ClassroomContainer.java 装classroom对象的容器类
public class ClassroomContainer {
private Classroom[] classroom; //装存classroom对象的数组
private int currentCapacity; //当前容器的容量
private int currentIndex; //当前容器装了多少对象-1,因为存的是下标
private int increase=10; //每次容量不够时的增长量
public void put(Classroom classroom){ //将一个classroom对象装入容器
if(currentIndex>=currentCapacity-1) //容量不够则增加容量
increaseLength();
this.classroom[currentIndex++]=classroom;
}
public Classroom AllRandomGet(){ //随机获取容器中一个对象
int i=(int)((new java.util.Random().nextFloat())*currentIndex); //产生在[0,currentIndex)区间的随机整数
return classroom[i]; //返回产生随机数对应的对象
}
public Classroom randomGetButExcept(Classroom[] except){ //随机获取容器中除了排除数组中对象的其他对象
ClassroomContainer cc=new ClassroomContainer();
for(int i=0;i<currentIndex;i++){ //遍历当前容器的对象
for(int j=0;j<except.length;j++){ //遍历排除数组中的对象
if(except[j].equals(classroom[i])) //若相等则不予处理
continue;
else{
cc.put(classroom[i]); //若对象不在排除列表中则放入一个新容器
}
}
} //新容器中只放不在排除列表中对象
return cc.AllRandomGet(); //新容器中随机返回一个对象
}//以下为相应的其他方法
public ClassroomContainer(){
this(20);
}
public ClassroomContainer(int capacity){
classroom=new Classroom[capacity];
this.currentCapacity=capacity;
this.currentIndex=0;
}
private void increaseLength(){ //增长长度
increaseLength(increase);
}
private void increaseLength(int increase){
Classroom[] newClassroom=new Classroom[currentCapacity+increase];
for(int i=0;i<=currentIndex;i++)
newClassroom[i]=classroom[i];
classroom=newClassroom;
currentCapacity+=increase;
System.out.println("Capacity Increased");
}//main方法
public static void main(String[] args){
Classroom[] c=new Classroom[10];
Classroom[] forbid=new Classroom[3];
int[] count=new int[10]; //对id 0-9 的每个对象取得次数计数器
for(int i=0;i<10;i++)
count[i]=0;
for(int i=0;i<10;i++){
c[i]=new Classroom(i); //定义id号0-9的classroom对象
}
forbid[0]=c[1];
forbid[1]=c[2];
forbid[2]=c[3]; //将id为1,2,3的对象加入排除数组
ClassroomContainer cc=new ClassroomContainer();
for(int i=0;i<10;i++)
cc.put(c[i]); //将id 0-9的对像加入容器
for(int i=0;i<10000;i++){
count[cc.randomGetButExcept(forbid).getId()]++; //循环10000次,并对每个对象取得次数进行计数
}
for(int i=0;i<10;i++){
System.out.println(count[i]); //将计数结果打印出来
}
}
}本来按照想法,结果中对应id号1,2,3的计数器应该为0,即count[1-3]。可是结果完全出乎意料。以下是在netbeans中运行生成结果:
1112
760
768
725
1078
1157
1093
1069
1144
1094可以看到,count[1-3]确实是大幅度减小了,但是却不是预想的0。为了证明随机取得的随机性,用AllRandomGet()(完全随机获得)方法再做一次10000个循环的试验,结果如下:
1007
993
1012
1040
996
993
995
999
994
971
可见,结果基本上是符合随机的。所以结果我就觉得很奇怪了,我设计的方法应该是完全阻止而不是减少获取到排除数组中对象的次数。但是,结果并不完全符合想象,大家帮我看看这是怎么回事呢?ps:一般来说的覆盖equals()就要覆盖hashCode()对这里并不适用,我覆盖了hashCode()结果还是如上面一样,只是大幅度消减,而不是阻止。
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货