今更ながらJava9の新機能をまとめてみた

Posted by user on Friday, August 23, 2019

TOC

背景

今までJava8の案件が主だったのですが、最近Java12の案件にも参画させて頂いています。

ただ、開発している中でJava9以降の機能を使っておらず、使える機能がないかを調べる目的でまとめてみました。
今回使用するサンプルコードは以下に全て置いてあります。
https://github.com/somurieengieer/javaSelfTraining/blob/master/src/sample/java9newFunc/Java9sample.java

追加された機能

BigInteger

sqrt()の追加

BigIntegerで平方根取得のメソッドが追加されました。四捨五入するようで、√2は1を返します。

BigInteger bi1 = new BigInteger("9");
System.out.println(bi1.sqrt());
BigInteger bi2 = new BigInteger("2");
System.out.println(bi2.sqrt());
// sqrt()の返り値はBigIntegerのため、四捨五入されて1が返却される

Optional、Stream

ifPresentOrElse()の追加

Java8で追加されたOptional、Streamですが、Java9以降にいくつかメソッドが追加されているようです。Java8が展開された後に不足していた機能を充足するメソッド追加のようです。

ifPresentOrElse()ではOptionalの値が存在する場合としない場合の処理をまとめて記載することができます。

Optional<String> opt1 = Optional.ofNullable("hoge");
opt1.ifPresentOrElse(
        s -> System.out.println(s + " is exist"),
        () -> System.out.println("not exist")
);
Optional<String> opt2 = Optional.ofNullable(null);
opt2.ifPresentOrElse(
        s -> System.out.println(s + " is exist"),
        () -> System.out.println("not exist")
);

streamNullFilter()の追加

Optionalのstream処理をする際に、値がnullの項目を排除することができます。

List<String> searchList = new ArrayList<>(){
   {
      add("aaa");
      add("ddd");
      add(null);
   }};
List<Optional<String>> optList = searchList.stream().map(s -> Optional.ofNullable(s)).collect(Collectors.toList());
optList.stream().flatMap(Optional::stream).forEach(System.out::println);
// flatMap(Optional::stream)を使うことで、楽にnullを排除できるようになった
// 以前は.filter(Optional::isPresent).map(Optional::get)と書かなければいけなかった

List<String> searchList2 = List.of("aaa", "bbb", "ccc", "ddd");
Map<String, String> resultMap = new HashMap<>(){{
   put("aaa", "exist_a");
   put("ddd", "exist_b");
}};
searchList2.stream().flatMap(s -> Stream.ofNullable(resultMap.get(s)))
        .forEach(s -> System.out.println(s));
// このように"bbb"と"ccc”に紐づく値は取得できないためstreamから外すことができる

or()の追加

値がnullの場合に返す値を定義することができます。

Optional opt1 = Optional.ofNullable("hoge");
System.out.println(opt1.or(() -> Optional.of("not exist")).get());
Optional opt2 = Optional.ofNullable(null);
System.out.println(opt2.or(() -> Optional.of("not exist")).get());
// opt2がnullの場合、or内の処理結果を使用する

takeWhile()の追加

streamに対する中間操作として使われます。streamの先頭から条件処理結果がfalseになるまでの値を返します。

List<Integer> list = List.of(3,5,1,3,8,8,2,4,2,3,5,8);
list.stream().takeWhile(i -> i < 6).forEach(System.out::println);
// i < 6の条件がfalseになるまでの値のstreamを返す

dropWhile()の追加

takeWhile()とは逆に、streamの先頭から条件処理結果がtrueの間の値を削除したstreamを返します。

List<Integer> list = List.of(3,5,1,3,8,8,2,4,2,3,5,8);
list.stream().dropWhile(i -> i > 2).forEach(System.out::println);
// i < 3の条件がtrueの間の値を削除したstreamを返す

List

of()の追加

Listの静的なファクトリメソッド。イミュータブルであるため扱いに注意。

List list = List.of("aaa", "bbb", "ccc");
list.stream().forEach(System.out::println);
// イミュータブルのため注意
// list.add("add is not allowed"); <- throw UnsupportedOperationException

モジュール機能

モジュールの概念が追加されました。

外部へ公開するpackageと公開しないpackageを区別することができ、公開している想定のないpackageへの意図しないアクセスを制限することができます。
以下の通り、外部へ公開するpackageを指定することができます。
使用用途はこちらの記載がわかりやすかったです。

jshell機能の追加

Javaを対話型で実行するためのツールです。以下のように起動することができます。

$ jshell
手軽に動作確認できるようになるので練習用に丁度よいですね。このような対話型評価環境をREPL(Read, Evaluate, Print, Loop の頭文字)と呼ぶようです。

ガベージコレクションのデフォルトがG1に変更

ガベージコレクションには以下の種類があります。

  • シリアルGC
  • パラレルGC
  • CMS
  • G1GC シングルコア環境ではシリアルGCがデフォルト、マルチコア環境ではパラレルGCがデフォルトでした。

Java9からはG1GCがデフォルトになります。(明確な情報が見つかりませんでしたが
CMSとG1GCがコンカレントGCであるため、マシン性能が求められます。ある程度スケールアップ/スケールアウトできる環境が当たり前になってきたことがデフォルト値変更の背景かもしれません。 ちなみにJava11が例ですが、以下サイトによると低スペックマシンでは引き続きシリアルGCが動くようです。
G1GCがデフォルトなのはマルチコア環境のみっぽいですね。業務で必要になったら詳細に調べる必要がありそうです。 https://matsumana.info/blog/2018/12/09/java11-g1gc-default/

所感

Java8の新機能として追加されたOptional、Streamに関する機能追加が多かったですね。Java8の機能で代替できるものなので取り急ぎ必要なものは少ないです。

List.of(…)はかなり多用しそうですね。イミュータブル推しの流れが来ているのでしょうか。
ちなみに、日付に関する以下はJava8から追加されたようです。Java9以降かと思ってたけど違いました。
 ・LocalDate
 ・LocalDateTime
 ・DateTimeFormatter