Et Voilà|Javaデータ構造(一):私の百宝箱Collections

9554 ワード

Javaデータ構造といえば,Collectionの下で派生した各種リスト,set,およびMapの下のサブクラスは数え切れないほど種類が多いといえる.どのように使うかを選ぶのは、女の子たちが街をぶらぶらしてアクセサリーを買うのと同じで、靴に合わせて、服に合わせて、化粧に合わせて、いろいろに合わせなければなりません.詳細にまとめると,これらの構造を比較する前に,大黄はもう一つのクラスに興味を持っていた.Collectionsである.Collectionと似ていますね.そうですか.また実の兄弟ですか.No No No、名前は似ていますが、実は全く違うもので、誰が一生に何人か同じ名前の友达に会ったことがないようですが、名前がそっくりでも、違う個体です.
CollectionsとCollectionsの違い
名前を見るだけでは役に立たないので、jdkソースコードを直接開いて、この2つのクラスのjava docの重要な説明を見てみましょう.
Collection
The root interface in the collection hierarchy. A collection represents a group of objects, known as its elements.
Collections
This class consists exclusively of static methods that operate on or return collections. It contains polymorphic algorithms that operate on collections, "wrappers", which return a new collection backed by a specified collection, and a few other odds and ends.
木製であることはよく知られていますが、Collectionはオブジェクトのセット、すなわちその要素を含む基礎的なインタフェースです.Collectionsは静的メソッド、アクション、またはコレクションクラスを返します.つまり、このクラスは実際には「ツールクラス」です.CollectionとCollectionsのような関係の組み合わせでよく見られるのはArrayとArrays類ですが、見覚えがあるのではないでしょうか、あの大明湖畔のArrays.asListメソッド.ここでは編幅分析というペアを拡大しません.違いがわかったらCollectionsが何ができるか見てみましょう.swiss knifeかどうか見てみましょう.
百宝箱Collections——「ネットレッド」方法の紹介例
Collectionsには頻繁に使用され、ほとんど毎日顔を出す方法があり、集合類に対する特殊な要求の操作を大幅に便利にしています.
ソートします
順序の要件はCollectionの基本的な要件であり、ソートが必要な場合もあれば、混乱が必要な場合もあり、ある2つの要素を交換する位置を指定する必要がある場合もあるなど、大黄は以下の最も一般的ないくつかの方法を例に挙げて説明します.
  • sort(List list):List内のすべての要素を自然昇順に並べ替える
  • .
  • sort(List list,Comparator c):カスタムコンパレータによるソート
  • shuffle(List list):リスト内の要素をランダムに乱す.シャッフル
  • に似ている.
  • swap(List list,int i,int j):List中のiの要素とjの要素を交換
  • .
  • rotate(List list,int distance):すべての要素を指定する長さ
  • だけ右にシフトする.
  • reverse(List list):Listコレクション内の要素を1回逆順序に並べ替える
  • .
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    
    public class collectionTest {
        public static void main(String[] args) {
        String[]  testData={ "London", "Shanghai", "Paris", "Tokyo", "Cannes", "Berlin" };
        ArrayList dataList = new ArrayList(Arrays.asList(testData));
        System.out.println("Initial Order:" + dataList);
        //  
        Collections.sort(dataList);
        System.out.println("Order after sort:" + dataList);
        //  
        Collections.reverse(dataList);
        System.out.println("Order after reverse:" + dataList);  
        //  
        Collections.shuffle(dataList);
        System.out.println("Order after shuffle:" + dataList);
        //  
        Collections.swap(dataList, 1,2);
        System.out.println("Order after swap:" + dataList);
        //  
        Collections.rotate(dataList, 1);
        System.out.println("Order after rotate:" + dataList);
      }
    
    }
    

    それぞれの方法の変化を見てみましょう.
    Initial Order:[London, Shanghai, Paris, Tokyo, Cannes, Berlin]
    Order after sort:[Berlin, Cannes, London, Paris, Shanghai, Tokyo]
    Order after reverse:[Tokyo, Shanghai, Paris, London, Cannes, Berlin]
    Order after shuffle:[Paris, Tokyo, Berlin, London, Cannes, Shanghai]
    Order after swap:[Paris, Berlin, Tokyo, London, Cannes, Shanghai]
    Order after rotate:[Shanghai, Paris, Berlin, Tokyo, London, Cannes]
    

    置換を検索します
    検索と置換も同様に集合クラスにおける重要な概念であり,forループのような構造を無理に使用したくない場合は,以下の一般的な方法を熟練して運用すると効率が大幅に向上する.元のリストにShanghaiを追加し、次の方法の検証を開始します.binarySearch(List list,Object key):集合がソートされていることを前提として、指定されたオブジェクトのリスト内のインデックスを取得するには、二分探索法を使用します.
  • max(Collection coll):最大要素
  • を取得
  • min(Collection coll):最小要素
  • を取得
  • frequency(Collection Object o):コレクション内の指定した要素の出現回数を取得する
  • replaceAll(List list,Object old,Object new):指定した要素
  • を置き換えます.
  • fill(List list,Object obj):指定要素を使用してセット
  • を塗りつぶす.
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    
    public class collectionTest {
        public static void main(String[] args) {
        String[]  testData={ "London", "Shanghai", "Paris", "Tokyo", "Cannes", "Berlin","Shanghai" };
        ArrayList dataList = new ArrayList(Arrays.asList(testData));
        System.out.println("Initial Order:" + dataList);
        //   
        System.out.println("max:" + Collections.max(dataList));
        System.out.println("min:" + Collections.min(dataList));
        //         
        System.out.println("Frequency of Shanghai:" + Collections.frequency(dataList, "Shanghai"));
        //      
        Collections.replaceAll(dataList, "Shanghai", "Dubai");
        System.out.println("After replaceAll:" + dataList);
        
        // binarySearch
        System.out.println("binarySearch before sort:" + Collections.binarySearch(dataList, "London"));
        Collections.sort(dataList);
        System.out.println("Order after sort:" + dataList);
        System.out.println("binarySearch after sort:" + Collections.binarySearch(dataList, "London"));
    
        Collections.fill(dataList, "Beijing");
        System.out.println("After fill:" + dataList);
        
       }
    }
    

    結果は次のとおりです.
    Initial Order:[London, Shanghai, Paris, Tokyo, Cannes, Berlin, Shanghai]
    max:Tokyo
    min:Berlin
    Frequency of Shanghai:2
    After replaceAll:[London, Dubai, Paris, Tokyo, Cannes, Berlin, Dubai]
    binarySearch before sort:-3
    Order after sort:[Berlin, Cannes, Dubai, Dubai, London, Paris, Tokyo]
    binarySearch after sort:4
    After fill:[Beijing, Beijing, Beijing, Beijing, Beijing, Beijing, Beijing]
    

    ここでbinarySearchについてお話しします.二分法でソートして検索します.ソート前に出力された答えは間違っていますが、ソート後は正しいです.なぜですか.Jdkソースを見てみましょう.
     public static 
        int binarySearch(List extends Comparable super T>> list, T key) {
            if (list instanceof RandomAccess || list.size()
        int indexedBinarySearch(List extends Comparable super T>> list, T key) {
            int low = 0;
            int high = list.size()-1;
    
            while (low <= high) {
                int mid = (low + high) >>> 1;
                Comparable super T> midVal = list.get(mid);
                int cmp = midVal.compareTo(key);
    
                if (cmp < 0)
                    low = mid + 1;
                else if (cmp > 0)
                    high = mid - 1;
                else
                    return mid; // key found
            }
            return -(low + 1);  // key not found
        }
    
        private static 
        int iteratorBinarySearch(List extends Comparable super T>> list, T key)
        {
            int low = 0;
            int high = list.size()-1;
            ListIterator extends Comparable super T>> i = list.listIterator();
    
            while (low <= high) {
                int mid = (low + high) >>> 1;
                Comparable super T> midVal = get(i, mid);
                int cmp = midVal.compareTo(key);
    
                if (cmp < 0)
                    low = mid + 1;
                else if (cmp > 0)
                    high = mid - 1;
                else
                    return mid; // key found
            }
            return -(low + 1);  // key not found
        }
    

    ソート前の大黄の例では、どのように動作しているかを示します.
  • low=0; high=6; mid=3, value=Tokyo
  • low=0; high=2; mid=1, value=Dubai
  • low=2; high=2; mid=2, value=Paris
  • low=2; high=1; return -3

  • これがなぜ-3が現れたのか、ソートがないため、二分の考え方は最初から岐路に立っていた.だからこの方法の使用はやはり具体的な状況によって、あなたのデータが順番に並べられているかどうか、あなたが先に並べ替えてから検索することを受け入れることができるかどうか、これらはすべて考慮する必要があります.
    Wrapperの魔力
    大黄が貼ったjava docをよく見ると、Collectionsには「wrappers」があることに気づいたに違いない.私たちは一般的にパッケージに訳します.主な役割は、元のいくつかのCollectionクラスを特定の属性を持つCollectionにカプセル化することです.中でも重要なのはsynch wrappers:synchronizedXxx()であり、synchronizedList、synchronizedSetなどである.これらのメソッドは、指定した集合オブジェクトに対応する同期オブジェクトを返し、マルチスレッドが集合に同時にアクセスするときのスレッドのセキュリティ問題を解決します.これにより、concurrentパケットを使用する以外の別のマルチスレッドのデータ構造構造も提供される.もう1つの一般的なwrapper種は,このようなオブジェクトに変換すると,関連する動作が禁止される不変集合と統一的に呼ぶ.このようなwrapperには
  • emptyXxx():空の可変集合オブジェクト
  • を取得
  • singletonXxx():指定したオブジェクトのみを含む、可変集合オブジェクトを取得します.
  • unmodifiableXxx():指定された集合オブジェクトの可変ビュー
  • を取得します.
    いくつかの特別なニーズがある場合、例えばあなたの集合が外部に読み取り専用でなければならない場合は、これらのパッケージを使用することができます.簡単な例
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    
    
    public class collectionTest {
        public static void main(String[] args) {
        String[]  testData={ "London", "Shanghai", "Paris", "Tokyo", "Cannes", "Berlin","Shanghai" };
        ArrayList dataList = new ArrayList(Arrays.asList(testData));
        
        List unModifyList = (List) Collections.unmodifiableList(dataList);
        unModifyList.add("Madrid"); //    exception
        System.out.println("unModifyList:" + unModifyList);
        }
    }
    

    addでjavaが投げ出されたことがわかります.lang.UnsupportedOperationExceptionは、集合オブジェクトが可変ではないことを証明しています.
    Exception in thread "main" java.lang.UnsupportedOperationException
        at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055)
        at jianshu.collectionTest.main(collectionTest.java:15)
    
    

    について述べる
    Collectionsには他にもいろいろな方法があります.wrappers、ここでは一つ一つ紹介しません.興味があるのはjdkソースコードをめくることができます.仕事をよくするには、まず器を利し、正しいツールクラスの方法を熟知し、選択することで、集合クラスのオブジェクトに対する操作効率を大幅に向上させ、Javaデータ構造の核心部分を深く理解するために基礎を築くことができます.これもこのような優れたところです.
    Et voilà!