Java 11の新しい機能-いくつかの実用的なAPIを追加

9414 ワード

新しいネイティブはセットAPIを変更できません


Java 9から、JDKにはofメソッドとcopyOfメソッドがセット(List/set/Map)に追加され、可変のセットを作成することができます.

Question 1:可変集合とは何ですか。


コレクションの追加、削除、置換、ソートなどの操作はできません.そうしないとjavaが報告されます.lang.UnsupportedOperationExceptionエラー.サンプルコード:
List list = List.of("aa", "bb", "cc");
list.add("dd");

エラーメッセージ:
Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:71)
    at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:75)

拡張:Arrays.asList()が作成したコレクションも可変のコレクションです

Question 2:ofメソッドとcopyOfメソッドの違い


サンプルコード:
var list1 = List.of("aa", "bb", "cc");
var copy1 = List.copyOf(list1);
System.out.println(list1 == copy1);
//    : true

var list2 = new ArrayList();
var copy2 = List.copyOf(list2);
System.out.println(list2 == copy2);
//    : false

注意:varもJava 11が新たに発表した特性局所変数タイプ推定であり、ここでは後述しない.
第1セグメントコードと第2セグメントコードの差は多くありませんが、なぜ結果が異なるのでしょうか.彼らのソースコードを見てみましょう.
    static  List of(E e1, E e2, E e3) {
        return new ImmutableCollections.ListN<>(e1, e2, e3);
    }

    static final class ListN extends AbstractImmutableList
            implements Serializable {

        static final List> EMPTY_LIST = new ListN<>();

        @Stable
        private final E[] elements;

        @SafeVarargs
        ListN(E... input) {
            // copy and check manually to avoid TOCTOU
            @SuppressWarnings("unchecked")
            E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input
            for (int i = 0; i < input.length; i++) {
                tmp[i] = Objects.requireNonNull(input[i]);
            }
            elements = tmp;
        }

        @Override
        public boolean isEmpty() {
            return size() == 0;
        }

        @Override
        public int size() {
            return elements.length;
        }

        @Override
        public E get(int index) {
            return elements[index];
        }

        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            throw new InvalidObjectException("not serial proxy");
        }

        private Object writeReplace() {
            return new CollSer(CollSer.IMM_LIST, elements);
        }
    }
    static  List copyOf(Collection extends E> coll) {
        return ImmutableCollections.listCopy(coll);
    }

    static  List listCopy(Collection extends E> coll) {
        if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {
            return (List)coll;
        } else {
            return (List)List.of(coll.toArray());
        }
    }

ソースコードから分かるように、copyOfメソッドは、まずソースセットがAbstractImmutableListタイプであるかどうかを判断し、もしそうであれば直接返し、そうでなければofを呼び出して新しいセットを作成する.第2セグメントコードはnewで作成された集合であり,可変AbstractImmutableListクラスのサブクラスに属さないため,copyOfメソッドはまた新しいインスタンスを作成するのでfalseである.
拡張子:Set.を使用するof()メソッドでSetオブジェクトを作成する場合は、重複データを含めてはいけません.

Stream強化


StreamはJava 8の新しい特性で、私の前のブログではJava 8の新しい特性-Stream APIについて詳しく紹介しました.Java 9はStreamに4つの新しい方法を追加し始めた.

単一パラメータの構築方法をnullに追加


Java 8でnullの値を持つStreamを新規作成するとjavaがエラーになります.lang.Null PointerExceptionエラー.サンプルコード:
Stream stream = Stream.of(null);

エラー:
Exception in thread "main" java.lang.NullPointerException
    at java.util.Arrays.stream(Arrays.java:5004)
    at java.util.stream.Stream.of(Stream.java:1000)

エラー解析:


Streamを表示します.of()ソース
    @SafeVarargs
    @SuppressWarnings("varargs") // Creating a stream from an array is safe
    public static Stream of(T... values) {
        return Arrays.stream(values);
    }

    public static  Stream stream(T[] array) {
        return stream(array, 0, array.length);
    }

受信nullは配列オブジェクトとして解析され、その長さ情報にさらにアクセスし、Null PointerException異常を引き起こすことがわかります.
Java 11では、nullに転送できるofNullableメソッドが追加されました.タイプを推定できないため、返される値はObjectで、サンプルコードは以下の通りです.
Stream stream = Stream.ofNullable(null);
stream.forEach(System.out::println);

ソースコードから、nullが入力された場合、空のオブジェクトが返されることがわかります.
    public static Stream ofNullable(T t) {
        return t == null ? Stream.empty()
                         : StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
    }

takeWhileメソッドとdropWhileメソッドを追加


takeWhile


まず、サンプルコードを見てみましょう.
Stream stream = Stream.of(3, 6, 9, 12, 15);
stream.takeWhile(n -> n % 2 != 0)
        .forEach(System.out::println);

このコードを初めて見ると、ストリームの奇数を見つけて印刷するのが第一印象かもしれませんが、実際の出力は:
3
したがってtakeWhile法はn%2==0まで計算されると終了し,takeWhile法の役割は,ストリームから判定器が真の要素であることを取得し,要素が偽であると処理を終了することである.

dropWhile


上のtakeWhileと同じコード:
Stream stream = Stream.of(3, 6, 9, 12, 15);
stream.dropWhile(n -> n % 2 != 0)
        .forEach(System.out::println);

次の結果が返されます.
6 9 12 15
結果はtakeWhileとは正反対であり,dropWhile法の役割は,判定器が真である限り,偽になるまで元素を捨て,偽になった後のすべての元素を取り出すことである.

iterateリロード


ストリームの反復は、主にストリームの作成に使用され、初期値を指定した場合に処理され、処理された値を初期値として反復します.だからiterateは無限のストリームを作成します.サンプルコード:
Stream.iterate(1, t -> 2 * t + 1)
        .limit(10)
        .forEach(System.out::println);

無限ストリームには、数値オーバーフロー後、-1の値が繰り返されるという問題があります.Java 11は、反復がいつ終了するか、限られた反復が行われるかを指定するPredicate(判断条件)を提供するために最適化されています.サンプルコードは次のとおりです.
Stream.iterate(1, t -> t< 1000, t -> 2 * t + 1)
        .forEach(System.out::println);

一連の文字列処理方法を追加しました


文字列が空白かどうかを判断


サンプルコード:
String s1 = " \t \r
"; System.out.println(s1.isBlank()); // true

文字列の先頭と末尾の空白を削除


サンプルコード:
String s2 = "    \t  123\r
".strip(); System.out.println(s2); // 123

trim()のほとんどの場合、効果はstrip()に等しいが、trim()は符号値が32以下の空白文字しか除去できず、中国語の場合の空白文字は除去できず、strip()はすべての言語の空白を除去できる

末尾/先頭スペースの削除


サンプルコード:
String s2 = "    \t  123\r
"; System.out.println(s2.strip().length()); // 3 // System.out.println(s2.stripLeading().length()); // 5 // System.out.println(s2.stripTrailing().length()); // 10

文字列のコピー

String s3 = "     ";
System.out.println(s3.repeat(3));
//                

行数統計

String s2 = "    \t  123\r
123"; System.out.println(s2.lines().count()); //2

s2.lines()はストリームを取得し、文字列を改行文字カットに基づいてStreamに変換します.

Optional強化


OptionalはJavaに導入されたコンテナクラスで、主に空ポインタの異常を避けるために使用されています.私の前のブログでは、Java 8の新しい特性-Optionalコンテナクラスについて詳しく紹介しました.Java 11ではOpthonalもいくつかのクールな方法を追加しました.

ofNullableメソッド


前のStream拡張の説明を参照して、Optionalを使用します.of(T value);入力パラメータがnullの場合、空ポインタ異常が放出されるので、Java 11にofNullableが追加され、空ポインタと互換性がありますが、実際にnullが入力された後は注意してgetで受信できないので、orElseメソッドで受信したほうがいいです.サンプルコードは以下の通りです.
Optional optional = Optional.ofNullable(null);
//         ,        ,        
System.out.println(optional.orElse("     ")); //      

orElseThrowメソッド


orElseThrow()メソッドを使用して受信し、orElseThrow()に直接異常を投げ出すこともできます.
Optional optional = Optional.ofNullable(null);
System.out.println(optional.orElseThrow());

エラーは次のとおりです:Exception in thread"main"java.util.NoSuchElementException: No value present at java.base/java.util.Optional.orElseThrow(Optional.java:382)
ソースコードは次のとおりです.
    public T orElseThrow() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

orメソッド


or()メソッドを使用して、空のOptionalの場合に代替のOptionalを受信することもできます.サンプルコードは以下の通りです.
Optional optional = Optional.ofNullable(null);
System.out.println(optional.or(() -> Optional.of("     !"))
        .get()); //      !

InputStream強化


Java 11にはtransferToメソッドが追加され、入力ストリーム内のすべてのデータを出力ストリームに直接自動的にコピーします.これは、元のデータストリームを処理する際に非常に実用的な使い方で、書き込みサイクルを必要とせず、バッファも必要としません.サンプルコードは以下の通りです.
public void test() throws Exception {
    var classLoader = this.getClass().getClassLoader();
    var inputStream = classLoader.getResourceAsStream("file");
    try (var outputStream = new FileOutputStream("file2")) {
        inputStream.transferTo(outputStream);
    }
    inputStream.close();
}