Java 我的Intset类有什么问题吗?

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

我设计了使用ArrayList的新IntSet类。首先,我通过ArrayList扩展Intset,并启动实现方法。我在union()方法中遇到了一些问题。这是我的密码

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
      ,但该类包含第二个ArrayList
      IntSet
      。除掉其中一个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