![ループを書くのはやめてください。 Java 8 でコレクションを操作するためのベスト プラクティス トップ 10 - 1]()
ご存知のとおり、私たちの習慣は生まれつきのものです。そして、一度 の書き方に慣れてしまえば
for (int i = 0; i <......)
、この構造を再学習する必要はなくなるでしょう (特に、非常にシンプルでわかりやすいため)。ただし、ループは同じ基本操作を実行するために繰り返し使用されることが多く、繰り返しは非常に排除したいものです。Java 8 では、Oracle がこれを支援することを決定しました。以下は、時間とコードを大幅に節約する 10 の最良の収集方法です。
1. Iterable.forEach(コンシューマ <? Super T> アクション)
名前自体がそれを物語っています。引数として渡されたコレクションを反復処理し、その要素ごとにアクション ラムダ式を実行します。
List <Integer> numbers = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7));
numbers.forEach(s -> System.out.print(s + " "));
1 2 3 4 5 6 7
2. Collection.removeIf(Predicate<? super E> フィルター)
繰り返しますが、ここでは難しいことは何もありません。このメソッドはコレクションを反復処理し、一致する要素をすべて削除します
filter
。
List <Integer> numbers = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7));
numbers.removeIf(s -> s > 5);
numbers.forEach(s -> System.out.print(s + " "));
1 行で、5 より大きいすべての数値をリストから削除します。
3. Map.forEach(BiConsumer <? super K, ? super V> アクション)
この
forEach
メソッドは、インターフェイスを実装するクラスだけでなく
Collection
、 に対しても機能します
Map
。
Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
4. Map.compute (K キー、BiFunction<? Super K、? Super V、? Extends V> remappingFunction)
もう少し威圧的に見えますが、実際にはこれまでのものと同様にシンプルです。このメソッドは
key
、 の値を実行結果と等しく設定します
mappingFunction
。例えば:
Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
books.compute("Thinking in Java", (a,b) -> b + ", cool dude");
System.out.println("_______________________");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
_______________________
Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel, cool dude
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
『Javaで考える』の著者はやっぱりかっこいい!:)
5. Map.computeIfAbsent(K key, Function <? super K, ? extends V> マッピング関数)
Map
このメソッドは、そのキーを持つ要素がまだ存在しない場合にのみ、新しい要素を に追加します。割り当てられた値は、 を実行した結果になります
mappingFunction
。キーを持つ要素がすでに存在する場合、その要素は上書きされません。それはそのまま残るだけです。本に戻って新しい方法を試してみましょう。
Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
books.computeIfAbsent("Harry Potter and the Prisoner of Azkaban", b -> getHarryPotterAuthor());
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
これが私たちのものです
mappingFunction
:
public static String getHarryPotterAuthor() {
return "Joanne Rowling";
}
そして、新しい本は次のとおりです。
Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Harry Potter and the Prisoner of Azkaban. Author: Joanne Rowling
Book title: Lord of the Rings. Author: John Tolkien
6. Map.computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
ここでは と同じ原理です
Map.compute()
が、計算は を持つ項目が
key
すでに存在する場合にのみ実行されます。
Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
books.computeIfPresent("Eugene Onegin", (a,b) -> b = "Alexander Pushkin");
System.out.println("_________________");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
books.computeIfPresent("The Brothers Karamazov", (a,b) -> b = "Alexander Pushkin");
System.out.println("_________________");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
この関数への最初の呼び出しでは変更は行われませんでした。これは、「エフゲニー・オネーギン」というタイトルの本が .html ファイルに存在しないためです
Map
。しかし、2回目の電話で、プログラムは本の「カラマーゾフの兄弟」の著者をアレクサンドル・プーシキンに変更した。出力:
_________________
Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
_________________
Book title: The Brothers Karamazov. Author: Alexander Pushkin
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
7. Map.getOrDefault(オブジェクトキー, VdefaultValue)
このメソッドは に対応する値を返します
key
。キーが存在しない場合は、デフォルト値が返されます。
Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
String igor = books.getOrDefault("The Tale of Igor's Campaign", "Unknown author");
System.out.println(igor);
これはとても便利です:
Unknown author
8. Map.merge(K キー, V 値, BiFunction<? super V, ? super V, ? extends V> remappingFunction)
この方法でコードの行数が何行節約できるか計算するまでは至りませんでした。
key
が に存在しない場合Map
、またはvalue
このキーの が である場合null
、メソッドは渡されたkey-value
ペアを に追加しますMap
。
key
が存在し、その が存在する場合value != null
、メソッドはその値を の実行結果に変更しますremappingFunction
。
remappingFunction
が返された場合null
、 はkey
コレクションから削除されます。
Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
books.merge("Thinking in Java", "Bruce Eckel", (a, b) -> b + " and some coauthor");
books.forEach((a, b) -> System.out.println("Title: " + a + ". Author: "+ b));
出力:
Title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Title: Thinking in Java. Author: Bruce Eckel and some coauthor
Title: Crime and Punishment. Author: Fyodor Dostoevsky
Title: War and Peace. Author: Leo Tolstoy
Title: Lord of the Rings. Author: John Tolkien
*ごめんなさい、ブルース*
9. Map.putIfAbsent(K キー, V 値)
Map
以前は、ペアがまだ存在していない場合に に ペアを追加するには、次の操作を行う必要がありました。
Map <String, String> map = new HashMap<>();
if (map.get("Lord of the Rings") == null)
map.put("Lord of the Rings", "John Tolkien");
今ではすべてがはるかに簡単になりました。
Map<String, String> map = new HashMap<>();
map.putIfAbsent("Lord of the Rings", "John Tolkien");
10. Map.replace と Map.replaceAll()
少なくとも最後のではなく。
Map.replace(K key, V newValue)
そのようなキーが存在する場合、key
の値を に置き換えます。newValue
そうでない場合は、何も起こりません。
Map.replace(K key, V oldValue, V newValue)
は同じことを行いますが、 の現在の値がkey
に等しい場合に限りますoldValue
。
Map.replaceAll(BiFunction<? super K, ? super V, ? extends V> function)
それぞれをvalue
関数の結果に置き換えます。
例えば:
Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
books.replace("The Brothers Karamazov", "Bruce Eckel", "John Tolkien");
books.forEach((a, b) -> System.out.println("Title: " + a + ". Author: "+ b));
Title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Title: Thinking in Java. Author: Bruce Eckel
Title: Crime and Punishment. Author: Fyodor Dostoevsky
Title: War and Peace. Author: Leo Tolstoy
Title: Lord of the Rings. Author: John Tolkien
うまくいきませんでした!キー「カラマーゾフの兄弟」の現在の値は「ブルース・エッケル」ではなく「フョードル・ドストエフスキー」であるため、何も変更されていません。
Map books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
books.replaceAll((a,b) -> getCoolAuthor());
books.forEach((a, b) -> System.out.println("Title: " + a + ". Author: "+ b));
public static String getCoolAuthor() {
return "Cool author";
}
Title: The Brothers Karamazov. Author: Cool author
Title: Thinking in Java. Author: Cool author
Title: Crime and Punishment. Author: Cool author
Title: War and Peace. Author: Cool author
Title: Lord of the Rings. Author: Cool author
複雑な構成を必要とせずに、全体の値を簡単に変更できました
Map
。PS 新しいものに慣れるのはいつも難しいですが、これらの変化は本当に良いことです。いずれにせよ、私のコードのいくつかの部分は、以前よりも明らかにスパゲッティらしくなくなりました :) 学習頑張ってください!
GO TO FULL VERSION