2013-03-12 13 views
8

私はIteratorインターフェイスを実装する内部クラスを実装する必要がある大学の割り当てを持っています。イテレーターは、単一リンクリストのスーパークラスで機能します。Iteratorインターフェイス

現在、私の内部クラスは次のようになります。

private class ListIterator implements Iterator<V>{ 

    Node temp; 
    boolean nextCalled = false; 

    ListIterator(Node fo){ 
     this.temp = fo; 
    } 

    @Override 
    public boolean hasNext() { 
     if(temp != null){ 
      return true; 
     } 
     return false; 
    } 

    @Override 
    public V next() { 
     nextCalled = true; 
     return temp.getReprValue(); 
    } 

    @Override 
    public void remove() { 
     if(nextCalled && hasNext()){ 
      nextCalled = false; 
      removeElement(temp.getReprKey()); 
      temp = temp.getNext(); 
     } 

    } 

} 

今私の問題は、のhasNext()メソッドは、リストが実際に空である場合でもtrueを返すことです。他のすべてがうまくいくようです。おそらくどこかでロジックの欠陥を見落としてしまったかもしれませんが、私はそれを自分で見つけることはできません。

+1

'next'メソッドは値を返すだけでなく、何らかの理由でイテレータを次の位置に移動させることを前提としています –

+0

' next() 'メソッドで' temp'の値を変更するべきではありませんか? – ApproachingDarknessFish

+0

副作用として、イテレータと同じパッケージに['ListIterator']というインターフェース(http://docs.oracle.com/javase/6/docs/api/java/util/ListIterator.html)が既にあります。あなたは別の名前を選びたいかもしれません。 – Powerlord

答えて

5

イテレータ契約に必要なものを反映するように実装を変更しました。 next()は、最初の要素から開始し、呼び出しごとに現在の次の要素をリストの次の要素に変更するか、または例外をスローする必要があることを覚えておく必要がありますもし存在しなければ。

Iterator interface docを読んで、それを実装しそこから開始する必要がある方法を理解しておくとよいでしょう。

private class ListIterator implements Iterator<V> { 
    private Node next; 
    private boolean alreadyDeleted = false; 

    ListIterator(Node node){ 
     this.next = node; 
    } 

    @Override 
    public boolean hasNext() { 
     // because next is the current element. We need to iterate over all the elements 
     // from the collection. 
     return next != null; 
    } 

    @Override 
    public V next() { 
     if (next == null) { 
      throw new NoSuchElementException(); 
     } 

     Node current = next; 

     this.next = current.getNext(); 
     this.alreadyDeleted = false; // it's better to try to elimate this state variable. You can try to do in another way, if yours removeElement returns something 

     return current; 
    } 

    @Override 
    public void remove() { 
     if (alreadyDeleted || next == null) { 
      throw new IllegalStateException(); 
     } 
     removeElement(next.getReprKey()); 
     this.alreadyRemoved = true; 
    } 

} 
5

cursorを実装するか、リンクリストのノードがnextを認識している場合は、次の要素があるかどうかを尋ねてください。 カーソルが大きければ、長さ/あなたのノードにはnextがありません。hasNext()でfalseを返します。

hasNext()メソッドでこれをすべて行います。 hasNext()がfalseの場合、next()に例外をスローすることは忘れないでください。例外をスローする唯一の時間であることを確認する必要があります。

私はあなたのリストの基礎となるデータ構造を知らないので、これらのうちどれが良いかを教えてもらえません。

2

hasNextは、現在のノード(temp)がnullでない場合にtrueを返します。

リンクされたリストの実装でヘッダーノードが使用されている場合、コンストラクタは常にfo!=nullを受け取り、hasNextはリストが空であってもtrueを返します。あなたの実装では、この事実を考慮する必要があります。

はあなたのコードに基づいて、

ListIterator(Node fo){ 
    this.temp = fo.getNext(); 
} 

は(空のリストについてheader.getNext()==null場合)トリックを行うことを思え。

2

いくつかのコードを減らし、そしてそれが

  • タッチより読みtemp
  • nextに使用ショートカット表記、
  • の名前を変更するようにするには、おそらくcurrentノードのいくつかの概念を持っている必要があり、

このようにすると、次のようになります。

private Node next; 
private Node current; //track deletion 

@Override 
public boolean hasNext() { 
    return next != null; 
} 

public Node getNext() { 
    if (hasNext()) { 
    current = next; 
    next = next.getNextNode(); 
    } 
    return current; 
} 

削除が現在のnullに設定される可能性があります。私たちは旗を必要としません(最初にgetNext()を呼び出す前に人が削除した場合、何もしないとうまくいっていると仮定して、実際に金に行きたい場合はremove()IllegalStateExceptionに投げてください)current == null

+0

この答えは、ノードと呼ばれる(メイン)関数を混乱させるようです。構造体の中でノードを後方に移動していない限り、ノードを現在の名前にし、次にそれを次のノードに設定する理由を明確にしないでください。 (これはgetNextがやるべきことではありません)btw私はショートカットの提案が好きです、それは本当にthoの一部ではありません。 –

+0

@JasonK。私はちょっと混乱していることを認めなければならない。私はどのように(main)関数が呼び出されているのか分かりませんし、どの例でも 'public static void main(String [] args)'はありません。この答えはAskerのために十分でした。私は4年前にそれに答えました。おそらくあなたは精緻化することができますか? –

+0

getNext()関数の先頭に "private Node current"を宣言することができますか?または他の関数で使用されていますか? –