ホームページ  >  記事  >  Java  >  Java クラス ライブラリ - Guava - 不変 (不変) コレクション

Java クラス ライブラリ - Guava - 不変 (不変) コレクション

黄舟
黄舟オリジナル
2017-01-19 13:24:201524ブラウズ

不変コレクションは、名前が示すように、コレクションが変更できないことを意味します。コレクションのデータ項目は作成時に提供され、ライフサイクル全体を通じて変更することはできません。

なぜ不変オブジェクトを使用するのでしょうか?不変オブジェクトには次の利点があります:

1. 信頼性の低いクライアントコードライブラリに安全に使用でき、これらのオブジェクトは信頼できないクラスライブラリでも安全に使用できます

2. スレッドセーフ: 不変オブジェクトはマルチスレッド下で安全です、競合状態はありません

3. 可変性をサポートする必要はなく、すべての不変コレクションの実装は、可変コレクションよりも効率的にメモリを使用できます

4 。将来も変更されないようにするには

不変オブジェクトは本質的に不変であるため、自然に定数として使用できます。これは、防御的プログラミングの技術的な実践方法です。

JDKでの不変コレクションの実装

不変コレクションを実装するためにJDKにはCollections.unmodifiableXXX系のメソッドが用意されていますが、以下にいくつか問題があります:

[code]import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Test;

public class ImmutableTest {
    @Test
    public void testJDKImmutable(){                                                                                                                                                                                                                                    
        List<String> list=new ArrayList<String>();                                                                               
        list.add("a");                                                                                                           
        list.add("b");                                                                                                           
        list.add("c");

        System.out.println(list);

        List<String> unmodifiableList=Collections.unmodifiableList(list); 

        System.out.println(unmodifiableList);

        List<String> unmodifiableList1=Collections.unmodifiableList(Arrays.asList("a","b","c")); 
        System.out.println(unmodifiableList1);

        String temp=unmodifiableList.get(1);
        System.out.println("unmodifiableList [0]:"+temp);

        list.add("baby");
        System.out.println("list add a item after list:"+list);
        System.out.println("list add a item after unmodifiableList:"+unmodifiableList);

        unmodifiableList1.add("bb");
        System.out.println("unmodifiableList add a item after list:"+unmodifiableList1);

        unmodifiableList.add("cc");
        System.out.println("unmodifiableList add a item after list:"+unmodifiableList);        
    }
}
[code][a, b, c]
[a, b, c]
[a, b, c]
unmodifiableList [0]:b
list add a item after list:[a, b, c, baby]
list add a item after unmodifiableList1:[a, b, c, baby]


1.使用するには すべての防御的なプログラミング コピーでこのメソッドを使用する必要があるのは面倒です

2. 安全ではありません: 元のカプセル化されたコレクション クラスを参照するオブジェクトがある場合、これらのメソッドによって返されるコレクションは真に不変ではありません。

3. 効率が低い: 返されるデータ構造の本質は依然として元のコレクション クラスであるため、同時変更チェックやハッシュ テーブル内の追加のデータ領域を含む操作のオーバーヘッドは、元のコレクションと同じです。

Guava の不変コレクション

Guava は、JDK の標準コレクション クラスの不変バージョンのシンプルで便利な実装と、いくつかの特殊なコレクション クラスの Guava 独自の不変実装を提供します。コレクション クラスを変更したくない場合、または定数のコレクション クラスを作成したい場合は、不変のコレクション クラスを使用することがプログラミングのベスト プラクティスです。

注: Guava の不変コレクション クラスのすべての実装は、null 値を拒否します。 Google の内部コードを包括的に調査したところ、コレクション クラスは 5% のケースでのみ null 値を許可し、95% のケースで null 値を拒否していることがわかりました。 null 値を受け入れることができるコレクション クラスが本当に必要な場合は、Collections.unmodifiableXXX の使用を検討してください。

不変コレクションの使用方法:

不変コレクションは次の方法で作成できます:

1. copyOf メソッドを使用します (例: ImmutableSet.copyOf(set))

2. of メソッドを使用します。 , ImmutableSet.of("a", "b", "c") または ImmutableMap.of("a", 1, "b", 2)

3. Builder クラスを使用します

[code]@Test
    public void testGuavaImmutable(){

        List<String> list=new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");
        System.out.println("list:"+list);

        ImmutableList<String> imlist=ImmutableList.copyOf(list);
        System.out.println("imlist:"+imlist);

        ImmutableList<String> imOflist=ImmutableList.of("peida","jerry","harry");
        System.out.println("imOflist:"+imOflist);

        ImmutableSortedSet<String> imSortList=ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");
        System.out.println("imSortList:"+imSortList);

         list.add("baby");
         System.out.println("list add a item after list:"+list);
         System.out.println("list add a item after imlist:"+imlist);

         ImmutableSet<Color> imColorSet =
               ImmutableSet.<Color>builder()
                   .add(new Color(0, 255, 255))
                   .add(new Color(0, 191, 255))
                   .build();

         System.out.println("imColorSet:"+imColorSet);       
    }

"b", " c", "a ", "d", "b")、このコレクションの走査順序は "a"、"b"、"c"、"d" です。

より賢い copyOf

copyOf メソッドは、あなたが思っているよりも賢いです。ImmutableXXX.copyOf は、適切な状況下で要素のコピーを回避します。最初に具体的な詳細は無視してください。しかし、その実装は一般に非常に「賢い」です。たとえば、

[code]@Test
    public void testCotyOf(){
        ImmutableSet<String> imSet=ImmutableSet.of("peida","jerry","harry","lisa");
        System.out.println("imSet:"+imSet);
        ImmutableList<String> imlist=ImmutableList.copyOf(imSet);
        System.out.println("imlist:"+imlist);
        ImmutableSortedSet<String> imSortSet=ImmutableSortedSet.copyOf(imSet);
        System.out.println("imSortSet:"+imSortSet);

        List<String> list=new ArrayList<String>();
        for(int i=0;i<20;i++){
            list.add(i+"x");
        }
        System.out.println("list:"+list);
        ImmutableList<String> imInfolist=ImmutableList.copyOf(list.subList(2, 18));
        System.out.println("imInfolist:"+imInfolist);
        int imInfolistSize=imInfolist.size();
        System.out.println("imInfolistSize:"+imInfolistSize);
        ImmutableSet<String> imInfoSet=ImmutableSet.copyOf(imInfolist.subList(2, imInfolistSize-3));
        System.out.println("imInfoSet:"+imInfoSet);
    }
[code]imSet:[peida, jerry, harry, lisa]
imlist:[peida, jerry, harry, lisa]
imSortSet:[harry, jerry, lisa, peida]
list:[0x, 1x, 2x, 3x, 4x, 5x, 6x, 7x, 8x, 9x, 10x, 11x, 12x, 13x, 14x, 15x, 16x, 17x, 18x, 19x]
imInfolist:[2x, 3x, 4x, 5x, 6x, 7x, 8x, 9x, 10x, 11x, 12x, 13x, 14x, 15x, 16x, 17x]
imInfolistSize:16
imInfoSet:[4x, 5x, 6x, 7x, 8x, 9x, 10x, 11x, 12x, 13x, 14x]



このコードでは、ImmutableList.copyOf(imSet) は一定の時間計算量で ImmutableSet の imSet.asList() をインテリジェントに返します。

一般に、ImmutableXXX.copyOf(ImmutableCollection) は線形複雑さのコピー操作を回避します。たとえば、次の状況では:

この操作は、カプセル化されたデータ構造の一定の複雑さの操作を利用する可能性があります。しかし、たとえば ImmutableSet.copyOf(list) は一定の複雑さで実装することはできません。

これによりメモリ リークは発生しません。たとえば、ImmutableList imInfolist があり、ImmutableList.copyOf(imInfolist.subList(0, 10)) を明示的に操作します。この操作により、不要になった hugeList 内の要素への参照を誤って保持することが回避されます。

ImmutableSet.copyOf(myImmutableSortedSet) のようなセット - 明示的なコピー操作のセマンティクスは変更されません。これは、ImmutableSet の hashCode() と equals() の意味がコンパレーターベースの ImmutableSortedSet とは異なるためです。

これらの機能は、防御的プログラミングのパフォーマンスのオーバーヘッドを最適化するのに役立ちます。

asList メソッド

すべての不変コレクションは、asList() の形式で ImmutableList ビューを提供します。たとえば、データを ImmutableSortedSet に置く場合、sortedSet.asList().get(k) を呼び出して最初の k 要素のセットを取得できます。

返される ImmutableList は、多くの場合、真のコピーではなく、一定の複雑さのビューです。言い換えれば、この返されたコレクションは通常の List よりもスマートです。たとえば、contains などのメソッドをより効率的に実装します。

[code]  @Test
    public void testAsList(){
        ImmutableList<String> imList=ImmutableList.of("peida","jerry","harry","lisa","jerry");
        System.out.println("imList:"+imList);
        ImmutableSortedSet<String> imSortList=ImmutableSortedSet.copyOf(imList);
        System.out.println("imSortList:"+imSortList);
        System.out.println("imSortList as list:"+imSortList.asList());
    }
[code]imList:[peida, jerry, harry, lisa, jerry]
imSortList:[harry, jerry, lisa, peida]
imSortList as list:[harry, jerry, lisa, peida]

 Guava集合和不可变对应关系

可变集合类型 可变集合源:JDK or Guava? Guava不可变集合 

Collection JDK ImmutableCollection 

List JDK ImmutableList 

Set JDK ImmutableSet 

SortedSet/NavigableSet JDK ImmutableSortedSet 

Map JDK ImmutableMap 

SortedMap JDK ImmutableSortedMap 

Multiset Guava ImmutableMultiset 

SortedMultiset Guava ImmutableSortedMultiset 

Multimap Guava ImmutableMultimap 

ListMultimap Guava ImmutableListMultimap 

SetMultimap Guava ImmutableSetMultimap 

BiMap Guava ImmutableBiMap 

ClassToInstanceMap Guava ImmutableClassToInstanceMap 

Table Guava ImmutableTable

以上就是Java-类库-Guava-Immutable(不可变)集合的内容,更多相关内容请关注PHP中文网(www.php.cn)!


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。