une - Quel est le point de surcharge des méthodes Convenience Factory pour les collections en Java 9




tableau d'objet java (4)

Java 9 est livré avec des méthodes d'usine pour créer des listes immuables. Enfin une création de liste est aussi simple que:

List<String> list = List.of("foo", "bar");

Mais il existe 12 versions surchargées de cette méthode, 11 avec 0 à 10 éléments et une avec var args.

static <E> List<E>  of(E... elements)

Même chose avec Set et Map .

Comme il existe une méthode var args, à quoi sert d'avoir 11 méthodes supplémentaires?

Ce que je pense, c’est que var-args crée un tableau, donc les 11 autres méthodes peuvent sauter la création d’un objet supplémentaire et dans la plupart des cas, 0 à 10 éléments le feront. Y a-t-il une autre raison à cela?


Ce modèle est utilisé pour optimiser les méthodes qui acceptent les paramètres varargs.

Si vous pouvez vous rendre compte que la plupart du temps vous n'en utilisez que deux, vous voudrez probablement définir une méthode surchargée avec la quantité de paramètres les plus utilisés:

public void foo(int num1);
public void foo(int num1, int num2);
public void foo(int num1, int num2, int num3);
public void foo(int... nums);

Cela vous aidera à éviter la création de tableaux lors de l'appel de la méthode varargs. Le modèle utilisé pour l'optimisation des performances:

List<String> list = List.of("foo", "bar");
// Delegates call here
static <E> List<E> of(E e1, E e2) { 
    return new ImmutableCollections.List2<>(e1, e2); // Constructor with 2 parameters, varargs avoided!
}

Ce qui est plus intéressant, c’est qu’à partir de 3 paramètres, nous déléguons à nouveau le constructeur de varargs:

static <E> List<E> of(E e1, E e2, E e3) { 
    return new ImmutableCollections.ListN<>(e1, e2, e3); // varargs constructor
}

Cela semble étrange pour le moment, mais comme je peux le deviner - ceci est réservé aux améliorations futures et en option, à la surcharge potentielle de tous les constructeurs List3(3 params), List7(7 params)... et etc.


Comme vous vous en doutez, il s’agit d’une amélioration des performances. Les méthodes Vararg créent un tableau "sous le capot", et avoir une méthode qui prend 1-10 arguments évite directement cette création de tableau redondant.


Selon le document Java : Les collections renvoyées par les méthodes de fabrique de commodité sont plus efficaces que leurs équivalents mutables.

Avant Java 9:

Set<String> set = new HashSet<>(3);   // 3 buckets

set.add("Hello");
set.add("World");
set = Collections.unmodifiableSet(set);

Dans l'implémentation ci-dessus de Set , il y a 6 objets en cours de création: le wrapper non modifiable; le HashSet , qui contient un HashMap ; la table des seaux (un tableau); et deux instances de noeud (une pour chaque élément). Si une machine virtuelle prend 12 octets par objet, 72 octets consomment en tant que surcharge, plus 28 * 2 = 56 octets pour 2 éléments. Ici, la grande quantité est consommée par la surcharge par rapport aux données stockées dans la collection. Mais dans Java 9, cette surcharge est très moindre.

Après Java 9:

Set<String> set = Set.of("Hello", "World");

Dans l'implémentation ci-dessus de Set , un seul objet est en train de créer et cela prendra beaucoup moins d'espace pour stocker les données en raison d'une surcharge minimale.


Vous pouvez également regarder l'inverse. Étant donné que les méthodes varargs peuvent accepter des tableaux, une telle méthode pourrait constituer un autre moyen de convertir un tableau en une List .

String []strArr = new String[]{"1","2"};
List<String> list = List.of(strArr);

L'alternative à cette approche consiste à utiliser Arrays.asList mais toute modification apportée à la List dans ce cas se refléterait dans le tableau, ce qui n'est pas le cas avec List.of Vous pouvez donc utiliser List.of lorsque vous ne souhaitez pas que la List et le tableau soient synchronisés.

Note La justification donnée dans la spécification semble être une micro-optimisation pour moi. (Cela a maintenant été confirmé par le propriétaire de l'API lui-même dans les commentaires d' another réponse)





java-9