¿Cómo puedo proporcionar una función de generador para Collection.toArray () usando JDK 11?

skomisa:

He actualizado Eclipse 4.8 Fotón ( http://download.eclipse.org/eclipse/downloads/drops4/S-4.9M2-201808012000/ ) para apoyar JDK 11 ( https://marketplace.eclipse.org/content/java- 11-support-Eclipse-fotón-49 ). Parece estar funcionando bien (Versión: 4.9 Build ID: I20180801-2000).

En JDK 11 hay una nueva anulación de método toArray()en java.util.Collection:

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

Es un método por defecto, pero no está anulado. Todo lo que hace es pasar el valor devuelto por la función de generador suministrado (usando un argumento no modificable de cero) a otro de anulación de toArray()que luego devuelve el contenido de la colección como una matriz.

Como se describe en el Javadoc para ese método, que puede ser llamado como esto:

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

Que funciona muy bien, y un conjunto de cuerdas de la longitud apropiada, correspondiente a la Collection<String>, se devuelve.

El Javadoc también afirma que " la implementación predeterminada llama a la función del generador con cero y luego pasa a la matriz resultante a toArray (T []) ".

Si proporciono mi propia función de generador que se consiga llamar (como se muestra por la println()salida de la consola), pero el valor de retorno de su apply()método parece ser ignorado. Es como si hubiera llamado toArray(String[]::new)independientemente del contenido de la matriz devuelta por mi función de generador.

Aquí está la 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));
    }
}

Aquí está la salida de la consola producido mediante la ejecución del MCVE:

array1: [Esto, es, una, lista, de, cuerdas]

intFunc: No. 0

intFunc: array que se devuelve: [A, B, C]

matriz2: [Esto, es, una, lista, de, cuerdas]

intFunc: No. 4

intFunc: array que se devuelve: [A, B, C, D]

array3: [Esto, es, una, lista, de, cuerdas]

Los espectáculos de salida que no importa lo que mi función de generador - la matriz que devuelve no se utiliza.

Mi pregunta es ¿cómo consigo esta nueva implementación de toArray()utilizar la matriz devuelta por mi función de generador, o estoy intentando algo que no es posible?


Actualizar sobre la base de los comentarios y la respuesta de Nicolai:

El problema con mi código de ejemplo no estaba con el generador, pero con mis casos de prueba. Pasaron a hacer que el generador para devolver una matriz con menos elementos que la colección, por lo que una nueva matriz se asignó en su lugar, para mantener con exactitud el número de elementos de la colección.

Un caso de prueba que devuelve una matriz más grande que las obras de captación como se esperaba. Por ejemplo, este código:

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

dicta la siguiente salida de la consola:

intFunc: No. 9

intFunc: array que se devuelve: [A, B, C, D, E, F, G, H, I]

array4: [Esto, es, a, lista, de, cuerdas, null, H, I]

La pregunta para Colecciones emptyList / Singleton / singletonList / Lista / Set toArray explica por qué hay un valor nulo dentro de la matriz devuelta.

Nicolai:

Como se ha señalado, toArray(IntFunction<T[]>)es un método por defecto que simplemente se remite a toArray(T[])(después de crear una matriz con la función dada). Si se echa un vistazo más de cerca a ese método, se encuentra la respuesta a su pregunta - a partir del 10 de Javadoc JDK (el énfasis es mío):

Devuelve una matriz que contiene todos los elementos de esta colección; el tipo de tiempo de ejecución de la matriz devuelta es la de la matriz especificada. Si los ajustes de recogida en la matriz especificada, se devuelve en la misma. De lo contrario, una nueva matriz se asigna con el tipo de tiempo de ejecución de la matriz especificada y el tamaño de esta colección.

Para la matriz se crea para ser utilizado, debe ser lo suficientemente largo para contener los elementos de la colección, por ejemplo:

public static void main(String[] args) {
    var createdArray = new AtomicReference<String[]>();
    var usedArray = List.of("A", "B", "C").toArray(__ -> {
        createdArray.set(new String[5]);
        return createdArray.get();
    });

    var message = String.format(
            "%s (length: %d; identical with created array: %s)",
            Arrays.toString(usedArray), usedArray.length, usedArray == createdArray.get());
    System.out.println(message);
}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=175776&siteId=1
Recomendado
Clasificación