長年にわたるJavaコレクションクラスリストのこれらのピットのインベントリ

現在の一部の高レベルプログラミング言語は、データ構造のさまざまなすぐに使用できる実装を提供します。たとえば、Javaプログラミング言語のコレクションフレームワークはさまざまな実装を提供します。コレクションクラスには、MapとCollectionが含まれます。リストは、私たちがよく使用するコレクションクラスの1つであり、多くのビジネスコードでは、リストなしでは実行できません。今日は、リストのいくつかの落とし穴を見てみましょう。

最初の落とし穴:Arrays.asListメソッドによって返されるリストは、操作の追加と削除をサポートしていません

たとえば、次のコードを実行します。

List <String>文字列= Arrays.asList( "m"、 "g"); 
strings.add( "h");复制代码

java.lang.UnsupportedOperationException例外がスローされますが、内部OSは何ですか?返されたArrayListに要素を追加できないのはなぜですか?今後も要素を追加できますか?、そして決定的にDebug Dafaを開きます:

返されるArrayListは、一般的に使用されるjava.util.ArrayListではなく、配列の内部クラスjava.util.Arrays.ArrayListであることがわかります。エントリメソッドArrays.asListのソースコードは次のとおりです。

public static <T> List <T> asList(T ... a){ 
    return new ArrayList <>(a); 
}复制代码

このメソッドは、配列の静的内部クラスjava.util.Arrays.ArrayListを返します。このクラスとjava.util.ArrayListも抽象クラスjava.util.AbstractListを継承していますが、このクラスのソースコードから、抽象親がないことがわかります。 AbstractListクラスのaddメソッドは、デフォルトでjava.lang.UnsupportedOperationExceptionをスローすることです。


このピットの根本的な原因は、呼び出しによって返される文字列のaddメソッドが抽象親クラスのaddメソッドから継承され、抽象親クラスのメソッドがデフォルトでjava.lang.UnsupportedOperationExceptionをスローすることです。

2番目のピット、Arrays.asListメソッドによって返される新しいリスト、およびメソッドの元のパラメーターグループの変更は、相​​互に影響します。

要素の追加または削除をサポートしない上記のピットに加えて、Arrays.asListメソッドには別のピットがあります。


上記のコードから、元の配列の変更がArrays.asListメソッドを介して取得した新しいリストに影響を与えることがわかり、java.util.Arrays.ArrayListのソースコードを深く掘り下げます。

private static class ArrayList <E> extends AbstractList <E> 
        implements RandomAccess、java.io.Serializable 
    { 
        private static final long serialVersionUID = -2764017481108945198L; 
        プライベートファイナルE [] a; 

        ArrayList(E [] array){ 
            a = Objects.requireNonNull(array); 
        } 

        ... 

     }   
复制代码

元の配列が直接使用されていることがわかります。配列は共有されており、相互に変更すると予期しないバグが発生する可能性があるため、Arrays.asListメソッドを使用して取得したリストに特に注意する必要があります。標準的な姿勢の1つは、ArrayList構築メソッドのパラメーターとして(たとえば、List stringList = new ArrayList <>(Arrays.asList(arrays)))、またはGuavaライブラリのLists.newArrayListを介してListを更新することです。返された新しいリストと元の配列は分離され、相互に影響を与えることはなくなります。

リストコレクションを直接トラバースして要素を削除する3番目のピットは、エラーを報告します

コレクション要素を直接トラバースする場合、要素を追加または削除するとエラーが報告されます。たとえば、次のコードを実行します。

List <String> stringList = Lists.newArrayList( "m"、 "g"、 "h"); 
for(String s:stringList){ 
    if(Arrays.asList( "m"、 "h")。contains(s)){ 
        stringList.remove(s); 
    } 
}复制代码

上記のコードは正常にコンパイルして渡すことができますが、実行時にjava.util.ConcurrentModificationExceptionがスローされます。ソースコードを見ると、delete elementメソッドremoveがコレクション構造を変更する、つまりmodCount(コレクションの実際の変更の数)が変更されることがわかります。ループプロセスでは、現在のリストコレクションmodCountの実際の変更数が、イテレーターの変更expectedModCountの数と比較されます。ExpectedModCountは初期化時のmodCountです。2つが等しくない場合、ConcurrentModificationExceptionが報告されます。この問題を解決するには、主に2つの方法があります。1。ArrayListのイテレーターメソッドを使用してトラバースし、メソッドを呼び出します。2. JDK 1.8以降では、removeIfメソッドを使用して削除できます。

最後に、難しい質問があります。ArrayListのremoveメソッドを呼び出して、intの基本タイプの番号とIntegerのパッケージタイプの番号を渡します。実行結果は同じですか?

やっと

ここを見てくれてありがとう、記事には欠陥があります、指摘することを歓迎します;それがうまく書かれていると思うなら、私に親指を上げてください。

おすすめ

転載: blog.51cto.com/11436461/2547410