12.コレクション(2)

章のまとめ

  • 要素グループの追加
  • 版画集
  • リストリスト

要素グループの追加

java.utilパッケージのArrays クラスCollectionsクラスには、一連の要素をCollectionに追加するための便利なメソッドが多数あります。

Arrays.asList()このメソッドは、配列または要素のコンマ区切りのリスト (可変引数パラメーターを使用) を受け取り、それをListオブジェクトに変換します。Collections.addAll()このメソッドは、 Collectionオブジェクト、および要素がCollectionに追加される配列またはカンマ区切りリストを受け入れます次の例は、これら 2 つのメソッドと、すべてのCollectionタイプに含まれるより一般的なメソッドを示していますaddAll()

// collections/AddingGroups.java
// Adding groups of elements to Collection objects
import java.util.*;

public class AddingGroups {
    
    
    public static void main(String[] args) {
    
    
        Collection<Integer> collection = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
        Integer[] moreInts = {
    
    6, 7, 8, 9, 10};
        collection.addAll(Arrays.asList(moreInts));
        // Runs significantly faster, but you can't
        // construct a Collection this way:
        Collections.addAll(collection, 11, 12, 13, 14, 15);
        Collections.addAll(collection, moreInts);
        // Produces a list "backed by" an array:
        List<Integer> list = Arrays.asList(16, 17, 18, 19, 20);
        list.set(1, 99); // OK -- modify an element
        // list.add(21); // Runtime error; the underlying
        // array cannot be resized.
    }
}

Collectionのコンストラクターは、別のCollectionを受け入れ、それを使用してそれ自体を初期化できます。したがって、 を使用してArrays.asList()このコンストラクターの入力を生成できます。ただし、実行速度が速く、要素を持たないCollection を構築して呼び出すのCollections.addAll()が簡単なので、これが推奨される方法です。Collections.addAll()

Collection.addAll()このメソッドはパラメータとして別のコレクションArrays.asList()のみを受け入れることができるため、柔軟性がありませんCollections.addAll()どちらのメソッドも可変個引数のパラメーター リストを使用します。

Arrays.asList()の出力をListとして直接使用することもできますが、ここでの基礎となる実装は配列であるため、サイズを変更できません。このListadd()に対してまたはを呼び出そうとするとremove()、これら 2 つのメソッドが配列のサイズを変更しようとするため、実行時に「サポートされていない操作」エラーが発生します。

// collections/AsListInference.java
import java.util.*;

class Snow {
    
    
}

class Powder extends Snow {
    
    
}

class Light extends Powder {
    
    
}

class Heavy extends Powder {
    
    
}

class Crusty extends Snow {
    
    
}

class Slush extends Snow {
    
    
}

public class AsListInference {
    
    
    public static void main(String[] args) {
    
    
        List<Snow> snow1 = Arrays.asList(new Crusty(), new Slush(), new Powder());
        //- snow1.add(new Heavy()); // Exception

        List<Snow> snow2 = Arrays.asList(new Light(), new Heavy());
        //- snow2.add(new Slush()); // Exception

        List<Snow> snow3 = new ArrayList<>();
        Collections.addAll(snow3,new Light(), new Heavy(), new Powder());
        snow3.add(new Crusty());

        // Hint with explicit type argument specification:
        List<Snow> snow4 = Arrays.<Snow>asList(new Light(), new Heavy(), new Slush());
        //- snow4.add(new Powder()); // Exception
    }
}

Snow4では、Arrays.asList()中央の「ヒント」 (すなわち)に注目してください。これは、生成された結果のリスト型の実際のターゲット型が何であるか<Snow>をコンパイラーに伝えます。これを明示的な型引数の指定と呼びます。Arrays.asList()

版画集

Arrays.toString()配列の印刷可能な形式を生成するために使用する必要があります。ただし、コレクションを印刷するのに助けは必要ありません。基本的な Java コレクションも紹介する例を次に示します。

// collections/PrintingCollections.java
// Collections print themselves automatically
import java.util.*;

public class PrintingCollections {
    
    
    static Collection fill(Collection<String> collection) {
    
    
        collection.add("rat");
        collection.add("cat");
        collection.add("dog");
        collection.add("dog");
        return collection;
    }

    static Map fill(Map<String, String> map) {
    
    
        map.put("rat", "Fuzzy");
        map.put("cat", "Rags");
        map.put("dog", "Bosco");
        map.put("dog", "Spot");
        return map;
    }

    public static void main(String[] args) {
    
    
        System.out.println(fill(new ArrayList<>()));
        System.out.println(fill(new LinkedList<>()));
        System.out.println(fill(new HashSet<>()));
        System.out.println(fill(new TreeSet<>()));
        System.out.println(fill(new LinkedHashSet<>()));
        System.out.println(fill(new HashMap<>()));
        System.out.println(fill(new TreeMap<>()));
        System.out.println(fill(new LinkedHashMap<>()));
    }
}

ここに画像の説明を挿入します

これは、Java コレクション ライブラリの 2 つの主要なタイプを示しています。それらの違いは、コレクションの各「スロット」に格納される要素の数です。Collectionタイプは、各スロットに 1 つの要素のみを格納できます。このようなコレクションには、特定の順序で要素のセットを保持するList 、要素を複製できないSet 、セットの一方の端にオブジェクトを挿入し、もう一方の端からのみオブジェクトを削除できるQueue が含まれます (この場合、これはシーケンスを表示する別の方法なので、表示されていません)。Map は、各スロットに 2 つの要素、つまり _key_ (キー) とそれに関連付けられた _value_ (値) を格納します。

デフォルトの印刷動作では、toString()コレクションによって提供されるメソッドを使用して、非常に読みやすい結果を生成します。コレクションは、角括弧で囲まれたコンテンツを各要素をカンマで区切って出力します。マップは中括弧で囲まれ、各キーと値は等号で接続されます (キーが左側、値が右側)。

最初のメソッドは、新しい要素を追加するメソッドを実装するfill()すべてのタイプのCollectionに適用されます。add()

ArrayListLinkedList は両方ともListのタイプであり、出力からわかるように、両方とも要素を挿入順序で保存します。2 つの違いは、特定の種類の操作を実行するときのパフォーマンスだけでなく、LinkedList にはArrayListよりも多くの操作が含まれますこれらについては、この章の後半でさらに詳しく説明します。

HashSetTreeSet、およびLinkedHashSetはSetのタイプです出力からわかるように、Set は同一の項目を 1 つだけ保持し、Set実装が異なると要素の保存方法も異なります。HashSet は要素を格納するかなり洗練された方法を使用しており、現時点では、この手法が要素を取得する最速の方法であることだけを知っておいてください。そのため、格納順序は重要ではないようです (多くの場合、何かが Set のメンバーであるかどうかのみを気にします。そして保存順序は関係ありません。重要ではありません)。格納順序が重要な場合は、比較ルールに従ってオブジェクトを並べ替えるTreeSetと、追加された順序でオブジェクトを並べ替えるLinkedHashSetを使用できます。

マップ(連想配列とも呼ばれます) は、単純なデータベースと同様に、キーを使用してオブジェクトを検索します。関連付けられたオブジェクトは値と呼ばれます。米国の州名と州都をリンクするマップがあるとします。オハイオ州の州都が必要な場合は、配列の添え字を使用するのとほぼ同じように、「オハイオ」をキーとして使用して検索できますこの動作のため、Map はキーごとに 1 回だけ保存されます。

Map.put(key, value)目的の値を追加し、それをキー (値の検索に使用) に関連付けます。Map.get(key)このキーに関連付けられた値を生成します。上記の例では、キーと値のペアを追加するだけであり、検索は実行されません。これについては後で説明します。

マップのサイズは自動的に変更されるため、ここでは指定 (または考慮) されていないことに注意してください。さらに、マップは、関連付けられたキーと値を表示するそれ自体を印刷する方法を知っています。

この例では、Mapの 3 つの基本スタイル、 HashMapTreeMapLinkedHashMapを使用します。

HashMap の実装では順序を制御するために非常に高速なアルゴリズムが使用されるため、 HashMapに保存されるキーと値の順序は挿入順序ではありません。TreeMap は比較ルールに従ってすべてのキーをソートし、LinkedHashMap はHashMap の検索速度を維持しながらキーの挿入順序に従ってソートします。

リストリスト

List は要素を特定の順序で保存することを約束します。ListインターフェイスはCollectionに基づいて多くのメソッドを追加し、 Listの途中で要素を挿入および削除できるようにします。

Listには 2 つのタイプがあります

  • 基本的なArrayList。要素へのランダム アクセスには優れていますが、Listの途中で要素を挿入および削除する場合は遅くなります。
  • LinkedListは、 Listの途中での低コストの挿入および削除操作を通じて、最適化された順次アクセスを提供します。LinkedList はランダム アクセスには比較的遅いですが、ArrayListよりも大きな機能セットを備えています。

次の例では、 TypeInformation の章のクラス ライブラリを高度に使用して、typeinfo.petsをインポートします。このクラス ライブラリには、Petクラス階層と、Petオブジェクトをランダムに生成するためのいくつかのユーティリティ クラスが含まれています。現時点では詳細をすべて知る必要はありませんが、知っておくべきことは 2 つだけです。

  1. PetクラスとPetのさまざまなサブタイプがあります。
  2. 静的メソッドは、new PetCreator().list()ランダムに選択されたPetオブジェクトで満たされたArrayListを返します。

ListFeature.java

import java.util.*;

public class ListFeatures {
    
    
    public static void main(String[] args) {
    
    
        Random rand = new Random(47);
        List<Pet> pets = new PetCreator().list(7);
        System.out.println("1: " + pets);
        Hamster h = new Hamster();
        pets.add(h); // Automatically resizes
        System.out.println("2: " + pets);
        System.out.println("3: " + pets.contains(h));
        pets.remove(h); // Remove by object
        Pet p = pets.get(2);
        System.out.println("4: " + p + " " + pets.indexOf(p));
        Pet cymric = new Cymric();
        System.out.println("5: " + pets.indexOf(cymric));
        System.out.println("6: " + pets.remove(cymric));
        // Must be the exact object:
        System.out.println("7: " + pets.remove(p));
        System.out.println("8: " + pets);
        pets.add(3, new Mouse()); // Insert at an index
        System.out.println("9: " + pets);
        List<Pet> sub = pets.subList(1, 4);
        System.out.println("subList: " + sub);
        System.out.println("10: " + pets.containsAll(sub));
        Collections.sort(sub); // In-place sort
        System.out.println("sorted subList: " + sub);
        // Order is not important in containsAll():
        System.out.println("11: " + pets.containsAll(sub));
        Collections.shuffle(sub, rand); // Mix it up
        System.out.println("shuffled subList: " + sub);
        System.out.println("12: " + pets.containsAll(sub));
        List<Pet> copy = new ArrayList<>(pets);
        sub = Arrays.asList(pets.get(1), pets.get(4));
        System.out.println("sub: " + sub);
        copy.retainAll(sub);
        System.out.println("13: " + copy);
        copy = new ArrayList<>(pets); // Get a fresh copy
        copy.remove(2); // Remove by index
        System.out.println("14: " + copy);
        copy.removeAll(sub); // Only removes exact objects
        System.out.println("15: " + copy);
        copy.set(1, new Mouse()); // Replace an element
        System.out.println("16: " + copy);
        copy.addAll(2, sub); // Insert a list in the middle
        System.out.println("17: " + copy);
        System.out.println("18: " + pets.isEmpty());
        pets.clear(); // Remove all elements
        System.out.println("19: " + pets);
        System.out.println("20: " + pets.isEmpty());
        pets.addAll(new PetCreator().list(4));
        System.out.println("21: " + pets);
        Object[] o = pets.toArray();
        System.out.println("22: " + o[3]);
        Pet[] pa = pets.toArray(new Pet[0]);
        System.out.println("23: " + pa[3].id());
    }
}

その他の関連カテゴリ:

Cat.java

public class Cat extends Pet {
    
    
  public Cat(String name) {
    
     super(name); }
  public Cat() {
    
     super(); }
}

Creator.java

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public abstract class Creator implements Supplier<Pet> {
    
    
    private Random rand = new Random(47);

    // The different types of Pet to create:
    public abstract List<Class<? extends Pet>> types();

    @Override
    public Pet get() {
    
     // Create one random Pet
        int n = rand.nextInt(types().size());
        try {
    
    
            return types().get(n)
                    .getConstructor().newInstance();
        } catch (InstantiationException |
                 NoSuchMethodException |
                 InvocationTargetException |
                 IllegalAccessException e) {
    
    
            throw new RuntimeException(e);
        }
    }

    public Stream<Pet> stream() {
    
    
        return Stream.generate(this);
    }

    public Pet[] array(int size) {
    
    
        return stream().limit(size).toArray(Pet[]::new);
    }

    public List<Pet> list(int size) {
    
    
        return stream().limit(size).collect(Collectors.toCollection(ArrayList::new));
    }
}

キムリック.java

public class Cymric extends Manx {
    
    
  public Cymric(String name) {
    
     super(name); }
  public Cymric() {
    
     super(); }
}

犬.java

public class Dog extends Pet {
    
    
  public Dog(String name) {
    
     super(name); }
  public Dog() {
    
     super(); }
}

エジプシャンマウ.java

public class EgyptianMau extends Cat {
    
    
  public EgyptianMau(String name) {
    
     super(name); }
  public EgyptianMau() {
    
     super(); }
}

ハムスター.java

public class Hamster extends Rodent {
    
    
  public Hamster(String name) {
    
     super(name); }
  public Hamster() {
    
     super(); }
}

個人.java

import java.util.Objects;

public class Individual implements Comparable<Individual> {
    
    
    private static long counter = 0;
    private final long id = counter++;
    private String name;

    public Individual(String name) {
    
    
        this.name = name;
    }

    // 'name' is optional:
    public Individual() {
    
    
    }

    @Override
    public String toString() {
    
    
        return getClass().getSimpleName() +
                (name == null ? "" : " " + name);
    }

    public long id() {
    
    
        return id;
    }

    @Override
    public boolean equals(Object o) {
    
    
        return o instanceof Individual &&
                Objects.equals(id, ((Individual) o).id);
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(name, id);
    }

    @Override
    public int compareTo(Individual arg) {
    
    
        // Compare by class name first:
        String first = getClass().getSimpleName();
        String argFirst = arg.getClass().getSimpleName();
        int firstCompare = first.compareTo(argFirst);
        if (firstCompare != 0) {
    
    
            return firstCompare;
        }
        if (name != null && arg.name != null) {
    
    
            int secondCompare = name.compareTo(arg.name);
            if (secondCompare != 0) {
    
    
                return secondCompare;
            }
        }
        return (arg.id < id ? -1 : (arg.id == id ? 0 : 1));
    }
}

マンクス.java

public class Manx extends Cat {
    
    
  public Manx(String name) {
    
     super(name); }
  public Manx() {
    
     super(); }
}

マウス.java

public class Mouse extends Rodent {
    
    
  public Mouse(String name) {
    
     super(name); }
  public Mouse() {
    
     super(); }
}

Mutt.java

public class Mutt extends Dog {
    
    
  public Mutt(String name) {
    
     super(name); }
  public Mutt() {
    
     super(); }
}

ペット.java

public class Pet extends Individual {
    
    
    public Pet(String name) {
    
    
        super(name);
    }

    public Pet() {
    
    
        super();
    }
}

ペットクリエイター.java

import java.util.*;

public class PetCreator extends Creator {
    
    
    // No try block needed.
    public static final
    List<Class<? extends Pet>> ALL_TYPES = Collections.unmodifiableList(Arrays.asList(
                    Pet.class, Dog.class, Cat.class, Rodent.class,
                    Mutt.class, Pug.class, EgyptianMau.class,
                    Manx.class, Cymric.class, Rat.class,
                    Mouse.class, Hamster.class));
    // Types for random creation:
    private static final
    List<Class<? extends Pet>> TYPES =
            ALL_TYPES.subList(
                    ALL_TYPES.indexOf(Mutt.class),
                    ALL_TYPES.size());

    @Override
    public List<Class<? extends Pet>> types() {
    
    
        return TYPES;
    }

    public static void main(String[] args) {
    
    
        System.out.println(TYPES);
        List<Pet> pets = new PetCreator().list(7);
        System.out.println(pets);
    }
}
/* Output:
[class reflection.pets.Mutt, class reflection.pets.Pug,
class reflection.pets.EgyptianMau, class
reflection.pets.Manx, class reflection.pets.Cymric, class
reflection.pets.Rat, class reflection.pets.Mouse, class
reflection.pets.Hamster]
[Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug]
*/

パグ.java

public class Pug extends Dog {
    
    
  public Pug(String name) {
    
     super(name); }
  public Pug() {
    
     super(); }
}

ラット.java

public class Rat extends Rodent {
    
    
  public Rat(String name) {
    
     super(name); }
  public Rat() {
    
     super(); }
}

げっ歯類.java

public class Rodent extends Pet {
    
    
  public Rodent(String name) {
    
     super(name); }
  public Rodent() {
    
     super(); }
}

印刷内容は以下の通りです。

ここに画像の説明を挿入します

出力をソース コードまで追跡できるように、印刷された行には番号が付けられます。出力の 1 行目には、元のペットリストが表示されます。配列とは異なり、リストは作成後に要素を追加または削除したり、リスト自体のサイズを変更したりできます。まさに、変更可能なシーケンスという価値があります。Hamsterを追加した結果は、出力の 2 行目で確認できます。オブジェクトはリストの最後に追加されます。

contains()このメソッドを使用して、オブジェクトがリストにあるかどうかを確認できます。オブジェクトを削除したい場合は、オブジェクトへの参照をremove()メソッドに渡すことができます。同様に、オブジェクトへの参照がある場合は、出力の 4 行目に示されているように、添え字を使用してListindexOf()のオブジェクトの場所を見つけることができます。

このメソッド (ルート クラスObjectのメソッド)は、要素がListに属しているかどうかを判断したり、要素のインデックスを検索したり、参照によってListから要素を削除したりするときに使用されます。ペットは一意のオブジェクトとして定義されているため、リスト内にすでに 2 つのCymricが存在する場合でも、新しいCymricオブジェクトを作成してメソッドに渡すと、結果は-1 (見つからないことを意味します) となり、次のことを試みます。このオブジェクトを削除するメソッドを呼び出すと、falseが返されます。他のクラスでは、の定義が異なる場合があります。たとえば、2 つのString は、その内容が同じであれば等しいと見なされますしたがって、予期せぬ事態を避けるために、リストの動作は動作に基づいて変化することに注意することが重要です。equals()indexOf()remove()equals()equals()

出力の 7 行目と 8 行目は、List内のオブジェクトと完全に一致するオブジェクトの削除が成功したことを示しています。

9 行目の出力とその前のコードに示すように、Listの中央に要素を挿入できます。しかし、これには問題が生じます。LinkedListの場合、リストの途中での挿入と削除は安価な操作です (この場合、リストの途中への真のランダム アクセスを除く)。一方、 ArrayList の場合、これはコストのかかる操作ですこれは、要素をArrayListの途中に挿入してはならず、 LinkedListに変換する方が良いという意味ですか? いいえ、それは単に問題に注意する必要があることを意味します。 ArrayListの途中で大量の挿入を実行し始めてプログラムが遅くなり始めた場合、潜在的な原因としてListの実装を検討する必要があります(見つかったこのクラスのボトルネックを解決する最良の方法は、プロファイラーを使用することです)。最適化は非常に難しい問題であるため、心配する必要がなくなるまで無視するのが最善の戦略です (ただし、これらの問題を理解しておくことは常に良い考えです)。

subList()メソッドは、より大きなリストからスライスを簡単に作成でき、スライスの結果がこのより大きなリストの元のメソッドに渡されると、当然のことながらtruecontainsAll()が返されます11 行目と 12 行目の出力でわかるように、順序は重要ではないことに注意してください。sub直感的に名前が付けられたメソッドメソッドを呼び出しても、 の結果には影響しません。舞台裏では、結果として得られるリストが元のリストになります。したがって、返されたリストへの変更は元のリストに反映され、その逆も同様です。Collections.sort()Collections.shuffle()containsAll()subList()

retainAll()このメソッドは実際には「交差の設定」操作であり、この場合はcopysubの両方にあるすべての要素を保持します。結果の動作はequals()メソッドによって異なることにもう一度注意してください。

14 行目の出力は、インデックス番号を使用して要素を削除した結果を示しています。インデックスを使用すると、 の動作を気にする必要がないため、オブジェクト参照によって要素を削除するよりも直感的ですequals()

removeAll()メソッドもequals()メソッドに基づいて実行されます。名前が示すように、パラメータList内のすべての要素をListから削除します。

set()Setクラスと競合する可能性があるため、メソッドの名前は時代錯誤に見えます。"replace" の機能はインデックス (最初の引数) の要素を 2 番目の引数で置き換えることであるため、ここでは "replace" を使用する方が適切かもしれません。

17 行目の出力は、 Listに対して、 CollectionメソッドaddAll()を使用してリストの末尾に新しいリストを追加するのではなく、元のリストの途中に新しいリストを挿入できるオーバーロードされたメソッドがあることを示しています。addAll()

出力の 18 ~ 20 行目は、isEmpty()およびclear()メソッドの効果を示しています。

出力の 22 行目と 23 行目は、メソッドを使用してコレクションを配列にtoArray()変換する方法を示しています。これは、引数のないバージョンがObjectsの配列を返すオーバーロードされたメソッドですが、このオーバーロードされたバージョンにターゲット型の配列を渡すと、指定された型の配列が生成されます (型チェックに合格したと仮定して)。(この例のように)引数の配列が小さすぎてリスト内のすべての要素を保持できない場合は、適切な次元の新しい配列が作成されます。Petオブジェクトには、結果の配列内のオブジェクトに対して呼び出すことができるメソッドがあります。toArray()id()

おすすめ

転載: blog.csdn.net/GXL_1012/article/details/132568129