Avec Google Guava (Google Commons), existe-t-il un moyen de fusionner deux listes de tailles égales en une seule liste, la nouvelle liste contenant les objets composites des deux listes d'entrée?
Exemple:
public class Person {
public final String name;
public final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "(" + name + ", " + age + ")";
}
}
et
List<String> names = Lists.newArrayList("Alice", "Bob", "Charles");
List<Integer> ages = Lists.newArrayList(42, 27, 31);
List<Person> persons =
transform with a function that converts (String, Integer) to Person
System.out.println(persons);
Serait sortie:
[(Alice, 42), (Bob, 27), (Charles, 31)]
A partir de Guava 21, cela est possible via Streams.Zip()
:
List<Person> persons = Streams.Zip(names.stream(), ages.stream(), Person::new)
.collect(Collectors.toList());
On dirait que ce n'est pas actuellement en goyave, mais est une fonctionnalité souhaitée. Voir ce problème de github , en particulier Iterators.Zip()
.
Imaginez qu'il s'agit d'une méthode de goyave:
for (int i = 0; i < names.size(); i++) {
persons.add(new Person(names.get(i), ages.get(i)));
}
Vous pouvez vous référer à underscore-Java library .
Underscore-Java
est un portage de Underscore.js
pour Java et la méthode Zip
peut atteindre cet objectif.
Voici un exemple de code et de sortie:
$.Zip(Arrays.asList("moe", "larry", "curly"), Arrays.asList("30", "40", "50"));
=> [[moe, 30], [larry, 40], [frisé, 50]]
Voici un moyen générique de compresser des listes avec Vanilla Java. En l'absence de tuples, j'ai choisi d'utiliser une liste d'entrées de la carte (si vous n'aimez pas utiliser les entrées de la carte, ajoutez une classe ZipEntry
supplémentaire ou quelque chose du genre).
public static <T1,T2> List<Map.Entry<T1,T2>> Zip(List<T1> zipLeft, List<T2> zipRight) {
List<Map.Entry<T1,T2>> zipped = new ArrayList<>();
for (int i = 0; i < zipLeft.size(); i++) {
zipped.add(new AbstractMap.SimpleEntry<>(zipLeft.get(i), zipRight.get(i)));
}
return zipped;
}
Pour prendre également en charge les tableaux:
@SuppressWarnings("unchecked")
public static <T1,T2> Map.Entry<T1,T2>[] Zip(T1[] zipLeft, T2[] zipRight) {
return Zip(asList(zipLeft), asList(zipRight)).toArray(new Map.Entry[] {});
}
Pour le rendre plus robuste, ajoutez des vérifications préalables sur les tailles de liste, etc., ou introduisez jointure gauche / jointure droite sémantique similaire aux requêtes SQL.
Voici une version sans itération explicite, mais elle devient plutôt moche.
List<Person> persons = ImmutableList.copyOf(Iterables.transform(
ContiguousSet.create(Range.closedOpen(0, names.size()),
DiscreteDomain.integers()),
new Function<Integer, Person>() {
@Override
public Person(Integer index) {
return new Person(names.get(index), ages.get(index));
}
}));
Ce n'est vraiment pas mieux que d'avoir une itération explicite, et vous voulez probablement un certain niveau de vérification des limites pour vous assurer que les deux entrées ont bien la même taille.