Java 我的Intset类有什么问题吗?
我设计了使用ArrayList的新IntSet类。首先,我通过ArrayList扩展Intset,并启动实现方法。我在union()方法中遇到了一些问题。这是我的密码Java 我的Intset类有什么问题吗?,java,Java,我设计了使用ArrayList的新IntSet类。首先,我通过ArrayList扩展Intset,并启动实现方法。我在union()方法中遇到了一些问题。这是我的密码 public class IntSet extends ArrayList<Integer>{ private static final long serialVersionUID = 1L; private ArrayList<Integer> intset; public I
public class IntSet extends ArrayList<Integer>{
private static final long serialVersionUID = 1L;
private ArrayList<Integer> intset;
public IntSet(){
this.intset = new ArrayList<Integer>();
}
public IntSet(ArrayList<Integer> intset){
this.intset = intset;
}
public void insert(int x){
this.intset.add(x);
}
@Override
public Integer remove(int x){
int index = intset.indexOf(x);
this.intset.remove(index);
return 1;
}
@Override
public int size(){
return this.intset.size();
}
@Override
public Integer get(int index){
return this.intset.get(index);
}
public boolean member(int x){
if(intset.indexOf(x)==-1) return false;
else return true;
}
public IntSet union(IntSet a){
IntSet intersectSet = new IntSet();
intersectSet.insert(0);
intersectSet.insert(1);
System.out.println(intersectSet.size());
System.out.println(intersectSet.contains(1));
for(int i=0; i<a.size(); i++){
}
return intersectSet;
}
public String toString(){
if(intset.size()==0) return "[]";
String s = "[" + intset.get(0).toString();
for(int i=1; i<intset.size(); i++){
s += "," + intset.get(i).toString();
}
return s += "]";
}
}
我构造新的Intset对象,然后将2个值(0,1)添加到intersectSet变量中
intersectSet.insert(0);
intersectSet.insert(1);
然后我打印了相交集的大小,它显示了2个,这是正确的
但是当我需要检查相交集中是否有1时?它给我的印象是错误的
System.out.println(intersectSet.contains(1));
事实上,它应该显示为true,因为在相交集中有整数1
我的代码有什么问题吗?我应该为IntSet类扩展ArrayList吗?您既在扩展ArrayList,又在管理自己的内部ArrayList对象,这意味着对于您覆盖的所有方法,您都在与
IntSet
成员变量交互,否则,您将与ArrayList超类使用的继承内部表示进行交互。如果重写contains
方法,您将获得正确的行为
我建议您放弃ArrayList的子类化,而是实现or接口,尽管这取决于您被要求解决的确切问题。您需要重写
contains
方法
public boolean contains(Object o) {
return intset.contains(o);
}
以及与其元素相关的其他ArrayList方法
在我看来,我并不是一个好的解决方案。你可以尝试更好的方法。关于课堂设计的一些建议:
- 不要让你的类扩展ArrayList。“集合”真的不应该扩展列表。但是,您可能应该实现Set。这将有额外的好处,编译器会告诉您需要为集合实现哪些方法
- 为了获得最快的性能(但需要更多的工作!),您可能需要使用内部数组而不是ArrayList
- 考虑使结构不可变,使用返回新副本的函数,而不是原地修改集合。根据您的使用情况,这可能是一个更好的解决方案,尤其是当您主要处理小的、不变的集合时
- 同样,根据您的使用情况,您可能希望覆盖hashCode和equals以实现基于值的相等
- 当使用ArrayList构造Intset时,理想情况下应该防御性地复制(克隆)ArrayList。如果有人更改了原始ArrayList,您不希望设置为更改
- 这里的问题是您实际上有两个ArrayList。
IntSet
类是一个ArrayList
,但该类包含第二个ArrayListIntSet
。除掉其中一个ArrayList。要演示这一点,请添加第二行:
System.out.println(intersectSet.contains(1));
System.out.println(intersectSet.intset.contains(1));
这将输出:
false
true
所以您必须做出选择,是从ArrayList继承还是包含ArrayList。当然,我在这里得到的是来自有效Java的第16项。为什么要
扩展ArrayList
,而不是在构造函数中this.intset=new ArrayList()
在剩下的代码中,不需要扩展类。我如何更改构造函数?给我一个主意。@Giffary,你可以保持构造函数的原样(使用组合),但是如果你这样做了,你就不应该扩展ArrayList。相反,实现List接口。Bloch在他的Set
示例中通过不扩展具体类HashSet
而是实现接口本身来实现这一点,通过使用List
执行此操作,您将不再受ArrayList
实现的负担,并且List
的插入与列表的实现分离。
false
true