2010-08-29 51 views
4

我設計了使用ArrayList的新IntSet類。首先,我通過ArrayList擴展Intset,然後開始實現方法。我在union()方法中遇到了一些問題。這裏是我的代碼...我的Intset類有什麼問題?

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 += "]"; 
    } 

} 

在方法

union(IntSet a); 

我建設工程新INTSET對象然後添加2值(0,1)轉換成intersectSet變量。

intersectSet.insert(0); 
intersectSet.insert(1); 

然後我打印尺寸的intersectSet它表明我2這是正確的!

但是當我需要檢查intersectSet是否有1?它表明我錯了。

System.out.println(intersectSet.contains(1)); 

其實應該告訴我正確的,因爲在intersectSet有整數1

什麼錯我的代碼,我應該爲INTSET類擴展的ArrayList?

+0

爲什麼你'擴展ArrayList '而不是在你的構造函數中'this.intset = new ArrayList ()',其餘代碼你不需要擴展你的類。 – jigfox 2010-08-29 10:04:48

回答

2

對類設計的一些建議:

  • 沒有你的類擴展的ArrayList。一個「集合」確實不應該延伸List。不過,你應該實現Set。這將爲編譯器提供額外的好處,告訴你需要爲一組實現什麼方法......
  • 爲了獲得最快的性能(但更多的工作!),您可能需要使用內部數組而不是ArrayList 。
  • 考慮使結構不可變,使用返回一個新副本的函數而不是改變該集合。根據您的使用情況,這可能是更好的解決方案,特別是如果您主要處理小型,不變的套件。
  • 再次取決於您的使用情況,您可能希望重寫hashCode並等於實現基於相等性的值
  • 當您使用ArrayList構造Intset時,理想情況下應該防禦性地複製(克隆)ArrayList。如果有人對原始ArrayList進行變異,你不希望你改變。
0

您既擴展了ArrayList,又管理着自己的內部ArrayList對象,這意味着對於所有已被覆蓋的方法,您正在與您的intset成員變量進行交互,否則就是與ArrayList使用的繼承內部表示形式交互超類。如果您重寫contains方法,您將獲得正確的行爲。

我建議你刪除ArrayList的子類,而不是實現ListSet接口,儘管這取決於你被要求解決的確切問題。

0

您需要覆蓋contains方法。

public boolean contains(Object o) { 
    return intset.contains(o); 
    } 

和與其元素相關的其餘ArrayList方法。

和我在我看來不是一個很好的解決方案。你可以嘗試更好的方法。

1

這裏的問題是,你實際上有2個ArrayLists。 IntSet類是A A ArrayList,但該類包含第二個ArrayList intset。擺脫這些ArrayLists之一。爲了證明這種添加第二條線:

System.out.println(intersectSet.contains(1)); 
System.out.println(intersectSet.intset.contains(1)); 

這將輸出:

false 
true 

所以,你將不得不做出選擇,我從ArrayList中繼承或者我包含一個ArrayList。當然,我在這裏得到Effective Java的第16項,Favor composition over inheritance

+0

我該如何更改構造函數?給我一個主意。 – Giffary 2010-08-29 10:21:53

+0

@Giffary,你可以保持它的構造方式(使用合成),但如果你這樣做,你不應該擴展ArrayList。相反,實現List接口。 Bloch在他的'Set'例子中通過不擴展具體類'HashSet'來實現這一點,但是通過實現接口本身,通過使用'List'來做這件事,你不再因'Ar​​rayList'的實現和'列表「與列表的實現分離。 – krock 2010-08-29 10:49:12