Java Language
コレクション
サーチ…
前書き
java.util
のコレクションフレームワークは、通常の配列では提供できない機能を持つ一連のデータの汎用クラスを提供します。
Collectionsフレームワークには、 Collection<O>
メインサブインタフェースList<O>
とSet<O>
、およびマッピングコレクションMap<K,V>
インタフェースが含まれています。コレクションはルートインターフェースであり、他の多くのコレクションフレームワークによって実装されています。
備考
コレクションは、その内部に他のオブジェクトのコレクションを格納できるオブジェクトです。 ジェネリックスを使用して、コレクションに格納されているデータの種類を指定できます。
コレクションは、通常、 java.util
またはjava.util.concurrent
名前空間を使用します。
Java 1.4.2以下はジェネリックをサポートしていません。そのため、コレクションに含まれる型パラメーターを指定することはできません。型の安全性を持たないことに加えて、キャストを使用してコレクションから正しい型を戻す必要があります。
Collection<E>
加えて、複数の主要なコレクションがあり、そのうちのいくつかにはサブタイプがあります。
-
List<E>
は、オブジェクトの順序付けられたコレクションです。これは配列に似ていますが、サイズの制限を定義していません。実装は、通常、新しい要素に対応するために内部的にサイズが大きくなります。 -
Set<E>
は重複を許可しないオブジェクトの集合です。-
SortedSet<E>
は要素の順序付けも指定するSet<E>
です。
-
-
Map<K,V>
はキーと値のペアの集合です。-
SortedMap<K,V>
は、要素の順序付けも指定するMap<K,V>
です。
-
Java 5では、新しいコレクション型が追加されました。
-
Queue<E>
は、特定の順序で処理される要素の集合です。この実装は、これがFIFOかLIFOかを指定します。これは、Stack
クラスを廃止します。
Java 6では、いくつかの新しいコレクションのサブタイプが追加されています。
-
NavigableSet<E>
は、特別なナビゲーションメソッドが組み込まれたSet<E>
です。 -
NavigableMap<K,V>
は、特別なナビゲーションメソッドを組み込んだMap<K,V>
です。 -
Deque<E>
はどちらの端からでも読み取れるQueue<E>
です。
上記の項目はすべてインターフェイスです。それらを使用するには、 ArrayList
、 HashSet
、 HashMap
、 PriorityQueue
などの適切な実装クラスを見つける必要があります。
各タイプのコレクションには、パフォーマンスメトリックとユースケースが異なる複数の実装があります。
Liskov Substitution Principleがコレクションのサブタイプに適用されることに注意してください。それは、されSortedSet<E>
期待して関数に渡すことができますSet<E>
。クラスの継承でコレクションを使用する方法の詳細については、GenericsセクションのBounded Parametersを参照すると便利です。
独自のコレクションを作成する場合は、インタフェースを実装する代わりに抽象クラス( AbstractList
など)のいずれかを継承する方が簡単です。
1.2より前のバージョンでは、代わりに次のクラス/インタフェースを使用する必要がありました。
-
ArrayList
代わりにVector
-
Map
代わりにDictionary
。 Dictionaryはインタフェースではなく抽象クラスでもあることに注意してください。 -
HashMap
代わりにHashtable
これらのクラスは廃止されており、最新のコードでは使用しないでください。
ArrayListの宣言とオブジェクトの追加
私たちは、作成することができますArrayList
(以下のList
インターフェース):
List aListOfFruits = new ArrayList();
List<String> aListOfFruits = new ArrayList<String>();
List<String> aListOfFruits = new ArrayList<>();
次に、メソッドadd
を使用してString
を追加します。
aListOfFruits.add("Melon");
aListOfFruits.add("Strawberry");
上記の例では、 ArrayList
はインデックス0にString
"Melon"を、インデックス1にString
"Strawberry"を含みます。
addAll(Collection<? extends E> c)
メソッドを使用して複数の要素を追加することもできます
List<String> aListOfFruitsAndVeggies = new ArrayList<String>();
aListOfFruitsAndVeggies.add("Onion");
aListOfFruitsAndVeggies.addAll(aListOfFruits);
今では "Onion"はaListOfFruitsAndVeggies
0インデックスに配置され、 "Melon"はインデックス1にあり、 "Strawberry"はインデックス2にあります。
既存のデータからコレクションを構築する
標準コレクション
Java Collectionsフレームワーク
個々のデータ値からList
を作成する簡単な方法は、 java.utils.Arrays
メソッドを使用することArrays.asList
:
List<String> data = Arrays.asList("ab", "bc", "cd", "ab", "bc", "cd");
すべての標準コレクション実装は、構築時に新しいコレクションにすべての要素を追加する引数として別のコレクションを取るコンストラクタを提供します。
List<String> list = new ArrayList<>(data); // will add data as is
Set<String> set1 = new HashSet<>(data); // will add data keeping only unique values
SortedSet<String> set2 = new TreeSet<>(data); // will add data keeping unique values and sorting
Set<String> set3 = new LinkedHashSet<>(data); // will add data keeping only unique values and preserving the original order
Google Guava Collectionsフレームワーク
もう一つの素晴らしいフレームワークは、さまざまなタイプの標準コレクションを構築するための素晴らしいユーティリティクラス(便利な静的メソッドを提供する)であるGoogle Guava
です。 Lists
とSets
:
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
...
List<String> list1 = Lists.newArrayList("ab", "bc", "cd");
List<String> list2 = Lists.newArrayList(data);
Set<String> set4 = Sets.newHashSet(data);
SortedSet<String> set5 = Sets.newTreeSet("bc", "cd", "ab", "bc", "cd");
コレクションのマッピング
Java Collectionsフレームワーク
Map<String, Object> map
場合と同様に、 Map<String, Object> map
すると、次のようにすべての要素を含む新しいマップを作成できます。
Map<String, Object> map1 = new HashMap<>(map);
SortedMap<String, Object> map2 = new TreeMap<>(map);
Apache Commons Collectionsフレームワーク
使い方Apache Commons
あなたが配列を使用して地図を作成することができArrayUtils.toMap
などMapUtils.toMap
:
import org.apache.commons.lang3.ArrayUtils;
...
// Taken from org.apache.commons.lang.ArrayUtils#toMap JavaDoc
// Create a Map mapping colors.
Map colorMap = MapUtils.toMap(new String[][] {{
{"RED", "#FF0000"},
{"GREEN", "#00FF00"},
{"BLUE", "#0000FF"}});
配列の各要素は、少なくとも2つの要素を含むMap.EntryまたはArrayのいずれかでなければなりません。最初の要素はキーとして使用され、2番目の要素は値として使用されます。
Google Guava Collectionsフレームワーク
Google Guava
フレームワークのユーティリティクラスの名前はMaps
です。
import com.google.common.collect.Maps;
...
void howToCreateMapsMethod(Function<? super K,V> valueFunction,
Iterable<K> keys1,
Set<K> keys2,
SortedSet<K> keys3) {
ImmutableMap<K, V> map1 = toMap(keys1, valueFunction); // Immutable copy
Map<K, V> map2 = asMap(keys2, valueFunction); // Live Map view
SortedMap<K, V> map3 = toMap(keys3, valueFunction); // Live Map view
}
Stream
を使用して、
Stream.of("xyz", "abc").collect(Collectors.toList());
または
Arrays.stream("xyz", "abc").collect(Collectors.toList());
参加リスト
ソースリストを変更せずにリストに参加するには、以下の方法を使用できます。
最初のアプローチ。より多くの行があるが、理解しやすい
List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);
2番目のアプローチ。 1行は少ないが読みやすい。
List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
3番目のアプローチ。サードパーティのApache commons-collectionsライブラリが必要です。
ListUtils.union(listOne,listTwo);
ストリームを使用すると、
List<String> newList = Stream.concat(listOne.stream(), listTwo.stream()).collect(Collectors.toList());
参考文献。 インタフェースリスト
ループ内のリストから項目を削除する
ループ内で項目をリストから削除するのは難しいのですが、これはリストのインデックスと長さが変更されたためです。
以下のリストでは、予期しない結果をもたらす例と正しい結果を与える例を示します。
List<String> fruits = new ArrayList<String>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Strawberry");
不正確
for
文の繰り返しでの削除"Banana"スキップ:
コードサンプルはApple
とStrawberry
のみを表示します。 Banana
は、 Apple
が削除されるとインデックス0
に移動するのでスキップされますが、同時にi
は1
に増やされます。
for (int i = 0; i < fruits.size(); i++) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
}
}
強化されたfor
ステートメントでの削除例外をスローする:
コレクションを繰り返して同時に変更するためです。
例外:java.util.ConcurrentModificationException
for (String fruit : fruits) {
System.out.println(fruit);
if ("Apple".equals(fruit)) {
fruits.remove(fruit);
}
}
正しい
Iterator
を使用したwhileループでの削除
Iterator<String> fruitIterator = fruits.iterator();
while(fruitIterator.hasNext()) {
String fruit = fruitIterator.next();
System.out.println(fruit);
if ("Apple".equals(fruit)) {
fruitIterator.remove();
}
}
Iterator
インターフェースには、この場合にのみ組み込まれたremove()
メソッドがあります。ただし、このメソッドはドキュメントでは「オプション」としてマークされており 、 UnsupportedOperationException
がスローされることがあります。
UnsupportedOperationException - このイテレータでremove操作がサポートされていない場合
したがって、この操作がサポートされていることを確認するためにドキュメントをチェックすることをお勧めします(実際には、コレクションがサードパーティのライブラリやCollections.unmodifiable...()
メソッドのいずれかを使用して取得された不変のものでない限り、操作はほぼ常にサポートされています)。
Iterator
を使用している間、 Iterator
が作成されたときからList
のmodCount
が変更されると、 ConcurrentModificationException
がスローされます。これは、同じスレッドまたは同じリストを共有するマルチスレッドアプリケーションで発生している可能性があります。
modCount
は、このリストが構造的に変更された回数を数えるint
変数です。構造の変更は、基本的に、 Collection
オブジェクトに対してadd()
またはremove()
操作が呼び出されることを意味します( Iterator
による変更はカウントされません)。 Iterator
が作成されると、このmodCount
格納され、現在のmodCount
がIterator
が作成されたときと同じであるかどうか、およびIterator
が作成されたときにList
すべての繰り返しにチェックされます。 modCount
値に変更がある場合、 ConcurrentModificationException
スローされます。
したがって、上記の宣言されたリストの場合、以下のような操作は例外をスローしません。
Iterator<String> fruitIterator = fruits.iterator();
fruits.set(0, "Watermelon");
while(fruitIterator.hasNext()){
System.out.println(fruitIterator.next());
}
しかし、 Iterator
を初期化した後に新しい要素をList
に追加すると、 ConcurrentModificationException
がスローされます。
Iterator<String> fruitIterator = fruits.iterator();
fruits.add("Watermelon");
while(fruitIterator.hasNext()){
System.out.println(fruitIterator.next()); //ConcurrentModificationException here
}
後方反復
for (int i = (fruits.size() - 1); i >=0; i--) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
}
}
これは何もスキップしません。このアプローチの欠点は、出力が逆であることです。ただし、ほとんどの場合、重要ではないアイテムを削除します。あなたはLinkedList
これを行うべきではありません。
順方向反復、ループインデックスの調整
for (int i = 0; i < fruits.size(); i++) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
i--;
}
}
これは何もスキップしません。 i
番目の要素がList
から削除されると、最初にインデックスi+1
位置する要素が新しいi
番目の要素になります。したがって、次の反復がスキップすることなく次の要素を処理するために、ループはi
を減分することができます。
「削除すべき」リストを使用する
ArrayList shouldBeRemoved = new ArrayList();
for (String str : currentArrayList) {
if (condition) {
shouldBeRemoved.add(str);
}
}
currentArrayList.removeAll(shouldBeRemoved);
このソリューションを使用すると、開発者は正しい要素がよりクリーンな方法で削除されているかどうかを確認できます。
Java 8では、以下の代替案が可能です。削除がループ内で行われる必要がない場合、これらはよりクリーンでより簡単です。
ストリームのフィルタリング
List
をストリーミングしてフィルタリングすることができます。適切なフィルターを使用して、望ましくない要素をすべて除去することができます。
List<String> filteredList =
fruits.stream().filter(p -> !"Apple".equals(p)).collect(Collectors.toList());
ここの他のすべての例とは異なり、この例では新しいList
インスタンスが生成され、元のList
変更されません。
removeIf
使用
ストリームの作成に必要なのは、一連のアイテムを削除することだけです。
fruits.removeIf(p -> "Apple".equals(p));
変更不可能なコレクション
変更可能な特性のために悪意のあるコードの脆弱性につながる可能性があるため、内部コレクションを公開するのは良い方法ではない場合があります。 「読み取り専用」コレクションを提供するために、Javaはその変更不可能なバージョンを提供します。
変更不可能なコレクションは、コレクション自体が変更できないことを保証する変更可能なコレクションのコピーであることがよくあります。変更しようとすると、UnsupportedOperationException例外が発生します。
コレクション内に存在するオブジェクトは引き続き変更できることに注意することが重要です。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MyPojoClass {
private List<Integer> intList = new ArrayList<>();
public void addValueToIntList(Integer value){
intList.add(value);
}
public List<Integer> getIntList() {
return Collections.unmodifiableList(intList);
}
}
変更不可能なコレクションを変更しようとすると、例外がスローされます。
import java.util.List;
public class App {
public static void main(String[] args) {
MyPojoClass pojo = new MyPojoClass();
pojo.addValueToIntList(42);
List<Integer> list = pojo.getIntList();
list.add(69);
}
}
出力:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055)
at App.main(App.java:12)
コレクションの繰り返し
リストを反復する
List<String> names = new ArrayList<>(Arrays.asList("Clementine", "Duran", "Mike"));
names.forEach(System.out::println);
並列処理が必要な場合
names.parallelStream().forEach(System.out::println);
for (String name : names) {
System.out.println(name);
}
for (int i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
//Creates ListIterator which supports both forward as well as backward traversel
ListIterator<String> listIterator = names.listIterator();
//Iterates list in forward direction
while(listIterator.hasNext()){
System.out.println(listIterator.next());
}
//Iterates list in backward direction once reaches the last element from above iterator in forward direction
while(listIterator.hasPrevious()){
System.out.println(listIterator.previous());
}
セットを反復する
Set<String> names = new HashSet<>(Arrays.asList("Clementine", "Duran", "Mike"));
names.forEach(System.out::println);
for (Iterator<String> iterator = names.iterator(); iterator.hasNext(); ) {
System.out.println(iterator.next());
}
for (String name : names) {
System.out.println(name);
}
Iterator iterator = names.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
マップを反復する
Map<Integer, String> names = new HashMap<>();
names.put(1, "Clementine");
names.put(2, "Duran");
names.put(3, "Mike");
names.forEach((key, value) -> System.out.println("Key: " + key + " Value: " + value));
for (Map.Entry<Integer, String> entry : names.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
// Iterating over only keys
for (Integer key : names.keySet()) {
System.out.println(key);
}
// Iterating over only values
for (String value : names.values()) {
System.out.println(value);
}
Iterator entries = names.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
不変の空のコレクション
不変の空のコレクションを使用するのが適切な場合もあります。 Collections
クラスは、そのようなコレクションを効率的に取得するメソッドを提供します。
List<String> anEmptyList = Collections.emptyList();
Map<Integer, Date> anEmptyMap = Collections.emptyMap();
Set<Number> anEmptySet = Collections.emptySet();
これらのメソッドは汎用的であり、返されたコレクションを割り当てられた型に自動的に変換します。つまり、例えばemptyList()
呼び出しは任意のタイプのList
割り当てられ、同様にemptySet()
およびemptyMap()
に対しても割り当てられます。
これらのメソッドによって返されるコレクションは、内容を変更するメソッド( add
、 put
など)を呼び出そうとするとUnsupportedOperationException
をスローするという点で不変です。これらのコレクションは、 null
を使用するか、 new
を使用してオブジェクトを作成するのではなく、空のメソッドの結果やその他のデフォルト値の代替として主に役立ちます。
コレクションとプリミティブ値
Javaのコレクションはオブジェクトに対してのみ機能します。つまり、Java Map<int, int>
はありません。代わりに、 Map<Integer, Integer>
ようにプリミティブ値をオブジェクトに囲む必要があります。 Javaオートボクシングにより、これらのコレクションの透過的な使用が可能になります。
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 17); // Automatic boxing of int to Integer objects
int a = map.get(1); // Automatic unboxing.
残念ながら、これのオーバーヘッドは相当です。 HashMap<Integer, Integer>
は、エントリあたり約72バイト(例えば、圧縮ポインタを持つ64ビットJVMで、256より大きい整数を仮定し、マップの50%のロードを想定します)を必要とします。実際のデータはわずか8バイトなので、膨大なオーバーヘッドが発生します。さらに、2レベルの間接指定(Map→Entry→Value)が必要ですが、不必要に遅いです。
プリミティブの大規模なコレクションを使用すると、パフォーマンスが大幅に向上するプリミティブデータ型(50%の負荷で1エントリあたり〜16バイトしか必要ない、つまりメモリが4倍少なく、間接化が1レベル少ない)のコレクションが最適化されたライブラリがいくつか存在しますJavaの値。
Iteratorを使用してListから一致する項目を削除する。
上の例では、ループ内のリストから項目を削除する例に気付きましたが、今回はIterator
インターフェースを使用して便利な別の例を考えました。
これは、あなたが取り除きたいリスト内の重複した項目を扱うときに役立つ可能性のあるトリックのデモンストレーションです。
注:これは、ループ内のリストから項目を削除する場合にのみ追加されます 。
だから、いつものようにリストを定義しましょう
String[] names = {"James","Smith","Sonny","Huckle","Berry","Finn","Allan"};
List<String> nameList = new ArrayList<>();
//Create a List from an Array
nameList.addAll(Arrays.asList(names));
String[] removeNames = {"Sonny","Huckle","Berry"};
List<String> removeNameList = new ArrayList<>();
//Create a List from an Array
removeNameList.addAll(Arrays.asList(removeNames));
次のメソッドは、2つのCollectionオブジェクトを取り、 nameList
要素と一致するremoveNameList
の要素を削除するという魔法を実行しnameList
。
private static void removeNames(Collection<String> collection1, Collection<String> collection2) {
//get Iterator.
Iterator<String> iterator = collection1.iterator();
//Loop while collection has items
while(iterator.hasNext()){
if (collection2.contains(iterator.next()))
iterator.remove(); //remove the current Name or Item
}
}
メソッドを呼び出し、 nameList
とremoveNameList
を次のようにremoveNames(nameList,removeNameList);
次の出力が生成されます。
名前を削除する前の配列リスト: James Smith Sonny Huckle Berry Finn Allan
名前を削除した後の配列リスト: James Smith Finn Allan
リスト内の繰り返し要素を削除するのに便利な、コレクションの簡単な使い方。
Iteratorまたはfor-eachループで使用する独自のIterable構造を作成する。
イテレータまたはfor-eachループを使用してコレクションを確実に反復できるようにするには、次の手順を実行する必要があります。
- 私たちが繰り返したいものは
Iterable
でiterator()
を公開するIterable
ありiterator()
。 -
hasNext()
、next()
およびremove()
オーバーライドしてjava.util.Iterator
設計します。
上記のエンティティを使用してリンクリストを反復可能にする単純な汎用リンクリストの実装を追加しました。
package org.algorithms.linkedlist;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class LinkedList<T> implements Iterable<T> {
Node<T> head, current;
private static class Node<T> {
T data;
Node<T> next;
Node(T data) {
this.data = data;
}
}
public LinkedList(T data) {
head = new Node<>(data);
}
public Iterator<T> iterator() {
return new LinkedListIterator();
}
private class LinkedListIterator implements Iterator<T> {
Node<T> node = head;
@Override
public boolean hasNext() {
return node != null;
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
Node<T> prevNode = node;
node = node.next;
return prevNode.data;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Removal logic not implemented.");
}
}
public void add(T data) {
Node current = head;
while (current.next != null)
current = current.next;
current.next = new Node<>(data);
}
}
class App {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>(1);
list.add(2);
list.add(4);
list.add(3);
//Test #1
System.out.println("using Iterator:");
Iterator<Integer> itr = list.iterator();
while (itr.hasNext()) {
Integer i = itr.next();
System.out.print(i + " ");
}
//Test #2
System.out.println("\n\nusing for-each:");
for (Integer data : list) {
System.out.print(data + " ");
}
}
}
出力
using Iterator:
1 2 4 3
using for-each:
1 2 4 3
これはJava 7以降で動作します。 Java 5とJava 6でも実行できるようにするには、次のものを置き換えます。
LinkedList<Integer> list = new LinkedList<>(1);
〜と
LinkedList<Integer> list = new LinkedList<Integer>(1);
互換性のある変更を組み込むことによって、他のバージョンに変更することができます。
落とし穴:同時修正例外
この例外は、イテレータオブジェクトによって提供されたメソッド以外のメソッドを使用してコレクションを反復処理している間にコレクションが変更された場合に発生します。たとえば、帽子のリストがあり、耳たぶのあるものをすべて削除したいとします。
List<IHat> hats = new ArrayList<>();
hats.add(new Ushanka()); // that one has ear flaps
hats.add(new Fedora());
hats.add(new Sombrero());
for (IHat hat : hats) {
if (hat.hasEarFlaps()) {
hats.remove(hat);
}
}
このコードを実行すると、コードが反復処理中にコレクションを変更するため、 ConcurrentModificationExceptionが発生します。同じリストで作業している複数のスレッドのうちの1つがコレクションを変更しようとしている間に他のスレッドが反復しようとしている場合、同じ例外が発生することがあります。複数のスレッドでのコレクションの同時変更は自然なことですが、同期ロック、同時変更に採用された特別なコレクション、初期からクローンされたコレクションの変更など、並行プログラミングツールボックスの通常のツールで処理する必要があります。
サブコレクション
リストsubList(int fromIndex、int toIndex)
ここからfromIndexはインクルーシブであり、toIndexは排他的です。
List list = new ArrayList();
List list1 = list.subList(fromIndex,toIndex);
- 指定された範囲にリストが存在しない場合は、IndexOutofBoundExceptionをスローします。
- リスト1に加えられた変更は、リストの同じ変更に影響します。これは、裏付コレクションと呼ばれます。
- fromIndexがtoIndex(fromIndex> toIndex)より大きい場合、IllegalArgumentExceptionがスローされます。
例:
List<String> list = new ArrayList<String>();
List<String> list = new ArrayList<String>();
list.add("Hello1");
list.add("Hello2");
System.out.println("Before Sublist "+list);
List<String> list2 = list.subList(0, 1);
list2.add("Hello3");
System.out.println("After sublist changes "+list);
出力:
サブリストの前[Hello1、Hello2]
サブリストの変更後[Hello1、Hello3、Hello2]
サブセットを設定する(fromIndex、toIndex)
ここからfromIndexはインクルーシブであり、toIndexは排他的です。
Set set = new TreeSet();
Set set1 = set.subSet(fromIndex,toIndex);
返されたセットは、その範囲外の要素を挿入しようとするとIllegalArgumentExceptionをスローします。
マップサブマップ(fromKey、toKey)
fromKeyはインクルーシブであり、toKeyは排他的です。
Map map = new TreeMap();
Map map1 = map.get(fromKey,toKey);
fromKeyがtoKeyより大きい場合、またはこのマップ自体が制限された範囲を持ち、fromKeyまたはtoKeyが範囲の境界外にある場合は、IllegalArgumentExceptionをスローします。
すべてのコレクションはバックアップされたコレクションをサポートします。これは、サブコレクションに加えられた変更がメインコレクションで同じ変更を行うことを意味します。