本ブログではアイフィリエイトによる収益を得ています。

[JavaSE8 Goldへの道] その12 コレクションフレームワークに追加されたdefaultメソッド

2018年4月24日火曜日

Java JavaSE8Gold

t f B! P L C
JavaSE8 Goldへの道(Upgrade to Java SE 8 Programmer 1Z0-810 試験対策)12回目です。

一連の記事は「JavaSE8Gold」ラベルを付けていきます。

インタフェースのdefaultメソッドがどういうものかついてはその3で触れていますが、今回は実際に追加されたものをご紹介していきます。


Mapに追加されたメソッド

getOrDefault

default V getOrDefault(Object key, V defaultValue)

Map<String, String> map = new HashMap<>();
map.getOrDefault("key", "default");

キーにマッピングが存在しない場合、第2引数の値を返します。
「もし戻り値がnullだったら・・・」みたいなことをやらずに済みます。
本当は前回のOptionalが使えればよかったでしょうが、そうすると型が変わってコンパイルし直しになってしまうので仕方ないですね。


putIfAbsent

default V putIfAbsent(K key, V value)

Map<String, String> map = new HashMap<>();
map.putIfAbsent("key", "value");

通常のMap#putと引数が同じですが、キーにマッピングがないときだけ追加します。
Map#containsKeyと二段階の操作が1回で済みます。


compute

default V compute(K key,
                  BiFunction<? super K,? super V,? extends V> remappingFunction)

Map<String, String> map = new HashMap<>();
String msg = "default";
map.compute("key", (k, v) -> v == null ? msg : msg + v);

キーと現在の値に対して、新しい値を計算するラムダ式を渡します。
まだマッピングが存在しない場合はラムダ式の第二引数にnullが渡されます。

ややこしいですが、これも複数の手順を1回で済ませられます。
例えばキーの出現回数をカウントするといった状況は、ループの中はこのメソッド1行で済みます。

ラムダ式がnullを返した場合、マッピングは削除されます。


computeIfAbsent

default V computeIfAbsent(K key,
                          Function<? super K,? extends V> mappingFunction)

Map<String, List<String>> map = new HashMap<>();
List<String> list = map.computeIfAbsent("key", k -> new ArrayList<>());
キーに対するマッピングが存在しない場合のみ、ラムダ式を実行して値を格納します。

初めて現れた時だけコンテナを生成したいというとき、putIfAbsentだとラムダ式ではないので無駄にオブジェクトが生成されてしまいます。
そういうときはこちらを使えば無駄がありません。

おまけにマッピングされていたらその値を、されていなかったらラムダ式で生成した値を返します。

APIドキュメントには「もっとも一般的な用途は、次のように初期のマップされた値またはメモ化された結果として機能する新しいオブジェクトを構築することです。」と書いてありますが、そのへんの話はきしださんのページにわかりやすく書いてあります。
とても便利!

ラムダ式がnullを返した場合、マッピングが削除されるのは同じです。


computeIfPresent

default V computeIfPresent(K key,
                           BiFunction<? super K,? super V,? extends V> remappingFunction)

Map<String, String> map = new HashMap<>();
map.computeIfPresent("key", (k,v) -> v + "+");

今度は逆にマッピングされているときだけラムダ式を呼び出し、値を置き換えます。

Mapを作る時ではなく、一度作ったMap内のペアに対して何かの別の処理をさせたいと言うときなんかに使えそうです。
こちらも戻り値として生成した値を返します。
ラムダ式がnullを返した場合、マッピングが削除されるのは同じです。


marge

default V merge(K key,
                V value,
                BiFunction<? super V,? super V,? extends V> remappingFunction)

map.merge(key, msg, String::concat);
上のを全部合わせたような感じです。
keyに対するマッピングが存在しない場合はvalueを格納、存在する場合remappingFunctionを呼び出して返された値を格納します。

例えばString#concatで同じキーの値を全部連結するなどが1行で書けます。

ラムダ式がnullを返した場合、マッピングが削除されるのは同じです。


forEach

default void forEach(BiConsumer<? super K,? super V> action)

map.forEach((k,v) -> System.out.println(k + v));
説明は不要でしょう。
Map#entrySetからforループしてやる必要がなくなります。



Collection

removeIf

default boolean removeIf(Predicate<? super E> filter)
コレクション内の要素について、ラムダ式の条件を満たすものを*全て*削除します。

CollectionListなどの多数のインタフェースのスーパーインタフェースなので、いろんなクラスで使えます。

他に、何度も登場してきたstreamparallelStreamメソッドもJava8で追加されたdefaultメソッドです。


List

replaceAll

default void replaceAll(UnaryOperator<E> operator)

List<String> list = new ArrayList<>();
  :
list.replaceAll(s -> s + "!");

リストの全要素に対して、ラムダ式の結果で置き換えます。
ラムダ式には元の要素が順次渡されます。



Iterable

forEach

default void forEach(Consumer<? super T> action)

「リストにforEachなかったっけ?」と思った方。
Collectionよりさらに親のjava.lang.Iterableに実装されています。

IterableはJava5で拡張for文を導入するときに追加されました。
java.util.Iteratorとは違うので注意です。



と、い、う、わ、け、で

ストリームAPIがよくわからんという方は、まずこの辺から入ってラムダ式に慣れていくといいかもしれません。

今回も以下のサイトとGoldの通常試験の参考書を参考にしています。
一連の記事は「JavaSE8Gold」ラベルを付けていきます。

それではみなさまよきガジェットライフを(´∀`)ノ


▼ブログを気に入っていただけたらRSS登録をお願いします!
▼ブログランキング参加中!応援よろしくお願いします。

ブログ内検索

自己紹介

猫とガジェットが好きなJava屋さんです。うつ病で休職後退職し、1年半の休養後に社会復帰。・・・が、いろいろあって再び退職。さらに1年休職の後に復帰して、なんとかSE続けてます。茶トラのすずと一緒に生活していましたが、2014年9月4日に亡くなって1人に。

より詳細なプロフィールはこちら↓

↓更新情報を受け取るにはフォローをお願いします!

Instagramでフォロー

※ヘッダー及びアイコンで使用しているドロイド君は、googleが作成、提供しているコンテンツをベースに複製したものです。

▼ココナラでメンターサービスを販売しています。招待コード「C3VG3」で1000ポイントもらえます。
▼欲しい物リスト

ブログ アーカイブ

QooQ