139 votes

Le moyen le plus simple de transformer une collection en tableau ?

Supposons que nous ayons un Collection<Foo> . Quelle est la meilleure façon (la plus courte en LoC dans le contexte actuel) de le transformer en Foo[] ? Tout bien connu les bibliothèques sont autorisées.

UPD : (un cas de plus dans cette section ; laissez des commentaires si vous pensez qu'il est utile de créer un autre fil pour cela) : Qu'en est-il de la transformation Collection<Foo> a Bar[]Bar a un constructeur avec 1 paramètre de type Foo c'est-à-dire public Bar(Foo foo){ ... } ?

1 votes

J'ai fait cette réponse avec une API alternative introduite dans le JDK-11 pour effectuer la même opération avec des performances similaires et l'explication qui l'accompagne. De plus, la syntaxe correspond à celle de l'API existante Stream.toArray de l'API du JDK.

274voto

doublep Points 9701

x est la collection :

Foo[] foos = x.toArray(new Foo[x.size()]);

39 votes

plus simple (plus facile) mais pas le meilleur (mémoire) : x.toArray(new Foo[0]) --- documentation : pas le temps de lire...

7 votes

@Carlos en fait, il utilise une meilleure mémoire que (new Foo[0]) . Selon la documentation de Collection.toArray, ` @param a le tableau dans lequel les éléments de cette collection doivent être stockés, s'il est suffisamment grand` ce qui signifie qu'il les stockera directement dans ce nouveau tableau. Si vous lui donnez un tableau de taille 0, il créera un nouveau tableau, ce qui signifie que vous avez un petit tableau et un grand tableau qui sont créés alors que cela n'est pas nécessaire.

4 votes

@glowcoder - mais cela peut être minimisé si vous définissez un tableau vide une fois comme une constante statique. C'est juste un indice pour toArray pour créer un tableau cible du bon type. Et dans ce cas, honnêtement, je ne me soucierais pas d'un seul tableau vide supplémentaire dans mon application. C'est bien en dessous du niveau de bruit.

38voto

Jules Points 5015

Solution alternative à la question mise à jour en utilisant Java 8 :

Bar[] result = foos.stream()
    .map(x -> new Bar(x))
    .toArray(size -> new Bar[size]);

38 votes

Cela peut être raccourci en Bar[] result = foos.stream().map(Bar::new).toArray(Bar[]::new);

0 votes

Du point de vue de la syntaxe, je préfère de loin la réponse acceptée. J'aimerais que les gens puissent tous passer à Python.

0 votes

@EricChen Passer de Java - "langage compilé et statiquement typé" à Python - un langage interprété et dynamiquement typé - parce que la syntaxe de codage et les lignes de chiffres diffèrent ? Ce n'est pas une bonne idée.

11voto

Andreas_D Points 64111

Si vous l'utilisez plus d'une fois ou dans une boucle, vous pouvez définir une constante

public static final Foo[] FOO = new Foo[]{};

et faire la conversion comme suit

Foo[] foos = fooCollection.toArray(FOO);

Le site toArray va prendre le tableau vide pour déterminer le type correct du tableau cible et créer un nouveau tableau pour vous.


Voici ma proposition pour la mise à jour :

Collection<Foo> foos = new ArrayList<Foo>();
Collection<Bar> temp = new ArrayList<Bar>();
for (Foo foo:foos) 
    temp.add(new Bar(foo));
Bar[] bars = temp.toArray(new Bar[]{});

1 votes

Ups, const n'est pas Java ! public static final Foo[] FOO = {}

1 votes

Pourquoi serait-elle publique ?

0 votes

@Zoltán - Pourquoi pas ? C'est immuable, donc ne présente pas de problème de sécurité. C'est un peu de désordre, mais il pourrait être utile dans d'autres codes, donc il est généralement inoffensif. Peut-être même créer une classe centrale avec toutes ces constantes, puis utiliser import static pour les atteindre.

3voto

Roman Points 21807

Voici la solution finale pour le cas de la section mise à jour (avec l'aide de Google Collections) :

Collections2.transform (fooCollection, new Function<Foo, Bar>() {
    public Bar apply (Foo foo) {
        return new Bar (foo);
    }
}).toArray (new Bar[fooCollection.size()]);

Mais, l'approche clé ici a été mentionnée dans la réponse du doublep (J'ai oublié pour toArray méthode).

1 votes

Voir mon commentaire sur la réponse de doublep concernant la sécurité des fils, qui s'applique également à cette solution. new Bar[0] évite la question.

2voto

OscarRyz Points 82553

Pour l'original, voir doublep réponse :

Foo[] a = x.toArray(new Foo[x.size()]);

Quant à la mise à jour :

int i = 0;
Bar[] bars = new Bar[fooCollection.size()];
for( Foo foo : fooCollection ) { // where fooCollection is Collection<Foo>
    bars[i++] = new Bar(foo);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X