Java: comment passer de List à Map sans itérer

J’ai une liste d’objects que je dois transformer en une carte où les clés sont une fonction de chaque élément et les valeurs sont des listes d’une autre fonction de chaque élément. Effectivement, il s’agit de regrouper les éléments en fonction de ceux-ci.

Par exemple, supposons une classe d’élément simple:

class Element { int f1() { ... } Ssortingng f2() { ... } } 

et une liste de ceux-ci:

 [ { f1=100, f2="Alice" }, { f1=200, f2="Bob" }, { f1=100, f2="Charles" }, { f1=300, f2="Dave" } ] 

alors je voudrais une carte comme suit:

 { {key=100, value=[ "Alice", "Charles" ]}, {key=200, value=[ "Bob" ]}, {key=300, value=[ "Dave" ]} } 

Est-ce que n’importe qui peut suggérer une manière succincte de faire ceci en Java sans itérer ? Une combinaison de la méthode de group de LambdaJ avec Maps.transform de Guava y Maps.transform presque, mais le group ne génère pas de carte.

Guava a Maps.uniqueIndex (valeurs itératives, Function keyFunction) et multimaps.index (valeurs itératives, Function keyFunction) , mais ne transforme pas les valeurs. Il y a quelques demandes pour append des méthodes utilitaires qui font ce que vous voulez, mais pour l’instant, vous devrez le faire vous-même à l’aide de Multimaps.index () et Multimaps.transformValues ​​():

 static class Person { private final Integer age; private final Ssortingng name; public Person(Integer age, Ssortingng name) { this.age = age; this.name = name; } public Integer getAge() { return age; } public Ssortingng getName() { return name; } } private enum GetAgeFunction implements Function { INSTANCE; @Override public Integer apply(Person person) { return person.getAge(); } } private enum GetNameFunction implements Function { INSTANCE; @Override public Ssortingng apply(Person person) { return person.getName(); } } public void example() { List persons = ImmutableList.of( new Person(100, "Alice"), new Person(200, "Bob"), new Person(100, "Charles"), new Person(300, "Dave") ); ListMultimap ageToNames = getAgeToNamesMultimap(persons); System.out.println(ageToNames); // prints {100=[Alice, Charles], 200=[Bob], 300=[Dave]} } private ListMultimap getAgeToNamesMultimap(List persons) { ImmutableListMultimap ageToPersons = Multimaps.index(persons, GetAgeFunction.INSTANCE); ListMultimap ageToNames = Multimaps.transformValues(ageToPersons, GetNameFunction.INSTANCE); // Multimaps.transformValues() returns a *lazily* transformed view of "ageToPersons" // If we want to iterate multiple times over it, it's better to create a copy return ImmutableListMultimap.copyOf(ageToNames); } 

Une méthode utilitaire réutilisable pourrait être:

 public static  ImmutableListMultimap keyToValuesMultimap(Iterable elements, Function keyFunction, Function valueFunction) { ImmutableListMultimap keysToElements = Multimaps.index(elements, keyFunction); ListMultimap keysToValuesLazy = Multimaps.transformValues(keysToElements, valueFunction); return ImmutableListMultimap.copyOf(keysToValuesLazy); } 

Je suppose que nous pourrions améliorer les génériques dans la signature en utilisant la Function Function ou quelque chose, mais je n’ai pas le temps d’aller plus loin …

Maintenant, avec Java8, vous pouvez le faire comme:

 static class Element { final int f1; final Ssortingng f2; Element(int f1, Ssortingng f2) { this.f1 = f1; this.f2 = f2; } int f1() { return f1;} Ssortingng f2() { return f2; } } public static void main(Ssortingng[] args) { List elements = new ArrayList<>(); elements.add(new Element(100, "Alice")); elements.add(new Element(200, "Bob")); elements.add(new Element(100, "Charles")); elements.add(new Element(300, "Dave")); elements.stream() .collect(Collectors.groupingBy( Element::f1, Collectors.mapping(Element::f2, Collectors.toList()) )) .forEach((f1, f2) -> System.out.println("{"+f1.toSsortingng() + ", value="+f2+"}")); } 

Il a été question d’append une API dans CollectionUtils d’Apache pour transformer une liste en carte, mais je ne vois aucune raison de ne pas utiliser de structure foreach. Y a-t-il un problème auquel vous êtes confronté? Transform va faire la même chose que vous pouvez obtenir facilement en foreach, la boucle ne peut être évitée.

MODIFIER:

Voici le lien vers la discussion sur le forum d’Apache http://apache-commons.680414.n4.nabble.com/Convert-List-to-Map-td747218.html

Je ne sais pas pourquoi tu ne veux pas itérer. JDK ne prend pas en charge la transformation, mais vous pouvez l’implémenter vous-même.

Si la performance vous inquiète, même si JDK l’a prise en charge, elle l’aura également réitérée.