6

JDK 11 ( https://marketplace.eclipse.org/content/java- 11-support-eclipse-photon-49 )。正常に動作しているようです (バージョン: 4.9 ビルド ID: I20180801-2000)。

JDK 11 ではtoArray()、Java.util.Collectionにメソッドの新しいオーバーライドがあります。

default <T> T[] toArray(IntFunction<T[]> generator) {
    return toArray(generator.apply(0));
}

これはデフォルトのメソッドですが、オーバーライドされません。提供されたジェネレーター関数 (ハードコーディングされたゼロの引数を使用) によって返された値を別のオーバーライドに渡し、toArray()コレクションの内容を配列として返すだけです。

そのメソッドの Javadoc で説明されているように、次のように呼び出すことができます。

String[] y = x.toArray(String[]::new);

これは正常に機能し、 に対応する適切な長さの文字列の配列Collection<String>が返されます。

Javadoc には、「デフォルトの実装ではジェネレーター関数がゼロで呼び出され、結果の配列が toArray(T[]) に渡される」とも記載されています。

独自のジェネレーター関数を提供すると、(println()コンソール出力に示されているように) 呼び出されますが、そのapply()メソッドの戻り値は無視されるようです。toArray(String[]::new)ジェネレーター関数によって返される配列の内容に関係なく、呼び出したようです。

MCVE は次のとおりです。

package pkg;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.IntFunction;

public class App {
    public static void main(String[] args) {

        IntFunction<String[]> intFunc = (int sz) -> {
            System.out.println("intFunc: sz: " + sz);
            if (sz == 0) {
                sz = 3;
            }
            String[] array = new String[sz];
            for (int i = 0; i < sz; i++) {
                array[i] = Character.toString('A' + i);

            }
            System.out.println("intFunc: array to be returned: " + Arrays.toString(array));
            return array;
        };

        Collection<String> coll = List.of("This", "is", "a", "list", "of", "strings");

        // Correctly returns the collection as an array, as described in JDK11 Javadoc.
        String[] array1 = coll.toArray(String[]::new);
        System.out.println("array1: " + Arrays.toString(array1) + '\n');

        // Use generator function to return a different collection as an array - doesn't work.      
        String[] array2 = coll.toArray(intFunc);
        System.out.println("array2: " + Arrays.toString(array2) + '\n');

        // Use generator function to return a different collection as an array - doesn't work.
        String[] array3 = coll.toArray(intFunc.apply(coll.size()-2));
        System.out.println("array3: " + Arrays.toString(array3));
    }
}

MCVE を実行して生成されるコンソール出力は次のとおりです。

array1: [This, is, a, list, of, strings]

intFunc: sz: 0

intFunc: 返される配列: [A, B, C]

array2: [This, is, a, list, of, strings]

intFunc: sz: 4

intFunc: 返される配列: [A, B, C, D]

array3: [This, is, a, list, of, strings]

出力は、ジェネレーター関数が何をするかは問題ではないことを示しています - それが返す配列は使用されていません。

私の質問は、ジェネレーター関数によって返された配列を使用するためにこの新しい実装を取得するにはどうすればよいですかtoArray()、それとも不可能なことを試みていますか?


コメントと Nicolai からの回答に基づいて更新します。

サンプル コードの問題は、ジェネレーターではなく、テスト ケースにありました。たまたまジェネレーターがコレクションよりも少ない要素の配列を返す原因となったため、代わりに新しい配列が割り当てられ、コレクション内の要素の数を正確に保持しました。

コレクションより大きい配列を返すテスト ケースは、期待どおりに機能します。たとえば、このコード:

    String[] array4 = coll.toArray(intFunc.apply(coll.size() + 3));
    System.out.println("array4: " + Arrays.toString(array4));

次のコンソール出力が得られます。

intFunc: sz: 9

intFunc: 返される配列: [A, B, C, D, E, F, G, H, I]

array4: [This, is, a, list, of, strings, null, H, I]

SO の質問Collections emptyList/singleton/singletonList/List/Set toArrayは、返された配列内に null 値がある理由を説明しています。

4

2 に答える 2