2010-11-24 7 views
2

こんにちは このコードではindexoutofboundsExceptionが返されますが、実際にはなぜわかりませんか? pointlistから、listのオブジェクトと同じオブジェクトを削除したいとします。IndexOutOfBoundsException

public void listOfExternalPoints(List<Point> list) { 
    System.out.println(list.size()); 
    System.out.println(pointList.size()); 
    int n = pointList.size(); 
    for (int i = pointList.size() - 1; i >= 0; i--) { 
     for (int j = 0; j < list.size(); j++) { 
      if (pointList.get(i)==(list.get(j))) { 
       pointList.remove(i); 
       n--; 
      } 
     } 
    } 

} 

ものprintlnの入れては次のようになります。また

​​

例外:

Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 60, Size: 60 
    at java.util.ArrayList.RangeCheck(ArrayList.java:547) 
    at java.util.ArrayList.get(ArrayList.java:322) 
    at ConvexHull.BlindVersion.listOfExternalPoints(BlindVersion.java:83) 

感謝。

答えて

10

ねえ、リストからいくつかの要素を削除しました。したがって、リストはループの開始時よりも小さくなります。

私はあなたが使用することをお勧め:

pointList.removeAll(list) 

イテレータ。

2

pointList.remove(i);

これにより、pointListのサイズが小さくなります。お役に立てれば。

6

pointList.remove(i)を実行するときは、内側のループから切り離す必要があります。それ以外の場合は、ループの次の繰り返しでもう一度削除したpointList.get(i)のインデックスを作成しようとします。そのため、例外が発生しています。

arrayListsが要素を削除すると、その要素が取り出され、その後にすべての要素が下に移動します。したがって、インデックス3を削除して4つの要素しかない場合、新しいarrayListのサイズは3にすぎず、範囲外のインデックス3を取得しようとします。

EDIT:これを行うには良い方法がある:

for(Point p : list) { 
    pointList.remove(p); 
} 

それは同じ効率を持っているが、より正しいだろう、私は思います。 ==は同じオブジェクトの参照を比較します。 removeメソッドが.equalsを使って平等をチェックするところで、あなたが望むと思うものです。

1

オブジェクトをpointListから削除すると、そのサイズが小さくなります。したがって、 "for j"ブロックの1回の反復で、PointListの2つの要素を削除して、他のすべての要素を左にシフトさせることができます。しかし、次の反復において、「i」は境界外位置(60)を参照する。

-1

リストを整数で反復するのではなく、Collectionsインタフェースでサポートされている各構成に対してforを使用します。

public void listOfExternalPoints(List<Point> list) { 
    for (Point pointListEntry : pointList) { 
     for (Point listEntry : list) { 
      if (pointListEntry == listEntry) { 
       pointList.remove(pointListEntry); 
      } 
     } 
    } 
} 

私はこれをデバッグしませんでしたが、それは私には正しいです。

+3

根本的なリストの形を変更するときにforeachループを使用することは明示的に安全ではありません。このコードは、pointListのiterator.next()でConcurrentModificationExceptionを発生させます。 –

+0

.removeはリストのO(n)操作です。だから、これはO(n^2)で実行できるときにO(n^3)になります。 – shoebox639

+0

イテレータは安全でしょうか? –

0

問題はループ評価の順番です。 pointListの長さを1回だけ評価し、それを再度チェックすることはありません。

pointListから最後のアイテムを削除しても、listの最後に達していない場合は、同じアイテムをpointListから再度取得しようとします。例外。これはshoebox639が気づいたものです。何かを取り除いた後で内側のループを壊した場合、外側のループの減分が問題を解決します。

ループの実行中に同じ要素から2つの要素を削除することは不可能です。リストの末尾のみを考慮しているため、現在の点を超える部分は削除対象外です。pointList一度に2つの要素を削除する場合は、次のiがリストから外れる程度にリストを短くすることは可能ですが、ここではこれを行うことはできません。しかし、他の同様のループで注意してください。

0

最初のループを実行するたびに(pointListを介して)、pointListの要素を複数削除することができます。 行にbreackpointを配置します。 pointList.remove(i); とデバッガでコードをステップ実行すると、それが表示されます。

関連する問題