J'ai un List<Valuta>
Qui peut être représenté (simplifié) de style JSON:
[{codice = EUR, description = Euro, ratio = 1}, {codice = USD, description = Dollars, ratio = 1.1}]
Je veux transformer cela en un Map<String, Valuta>
Comme ceci:
{EUR = {codice = EUR, description = Euro, ratio = 1}, USD = {codice = USD, description = Dollars, ratio = 1,1}}
J'ai écrit ce one-liner:
getValute().stream().collect(Collectors.groupingBy(Valuta::getCodice));
mais cela renvoie un Map<String, List<Valuta>>
au lieu de ce dont j'ai besoin.
Je suppose que la fonction mapping()
fonctionnerait pour moi, mais je ne sais pas comment.
En fait, vous devez utiliser Collectors.toMap
ici au lieu de Collectors.groupingBy
:
Map<String, Valuta> map =
getValute().stream()
.collect(Collectors.toMap(Valuta::getCodice, Function.identity()));
groupingBy
est utilisé pour regrouper les éléments d'un Stream en fonction d'une fonction de regroupement. 2 Les éléments de flux qui auront le même résultat avec la fonction de regroupement seront collectés dans un List
par défaut.
toMap
collectera les éléments dans un Map
où la clé est le résultat de l'application d'un mappeur de clés donné et la valeur est le résultat de l'application d'un mappeur de valeurs. Notez que toMap
, par défaut, lèvera une exception si un doublon est rencontré.
C'est un peu tard dans le jeu, mais essayez ceci:
Map<String, Valuta> map =
getValute().stream()
.collect(Collectors.groupingBy(Valuta::getCodice,
Collectors.collectingAndThen(
Collectors.toList(),
values -> values.get(0))));
Vous pouvez utiliser Collectors.toMap(keyMappingFunction, valueMappingFunction)
Map<String, Valuta> map = list
.stream()
.collect(Collectors.toMap(Valuta::getCodice, v -> v));
Vous pouvez remplacer v->v
Par Function.identity()
si vous le trouvez plus lisible.
Pas complètement lié à cette question, mais cas similaire calme. Si vous souhaitez grouper la liste par plusieurs paramètres et que vous devez ensuite renvoyer un objet de type différent en tant que valeur, vous pouvez essayer cette solution. L'espoir aide quelqu'un!
public Map<Integer, Map<String, ObjectTypeB>> setObjectTypeB(List<ObjectTypeA> typeAList) {
Map<Integer, Map<String, ObjectTypeB>> map = typeAList.stream()
.collect(groupingBy(ObjectTypeA::getId,
groupingBy(ObjectTypeA::getDate,
collectingAndThen(mapping(this::getObjectTypeB,toList()),values -> values.get(0)))));
return map;
}
public ObjectTypeB getObjectTypeB(ObjectTypeA typeA) {
ObjectTypeB typeB = new ObjectTypeB();
typeB.setUnits(typeA.getUnits());
return typeB;
}
Voici 3 méthodes.
public class Test1 {
static class Foo {
public int id, targetCost, actualCost;
public String ref;
public Foo(int id, String ref, int actualCost, int targetCost) {
this.id = id;
this.targetCost = targetCost;
this.actualCost = actualCost;
this.ref = ref;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getTargetCost() {
return targetCost;
}
public void setTargetCost(int targetCost) {
this.targetCost = targetCost;
}
public int getActualCost() {
return actualCost;
}
public void setActualCost(int actualCost) {
this.actualCost = actualCost;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
@Override
public String toString() {
return " [id=" + id + ", targetCost="
+ targetCost + ", " + "actualCost="
+ actualCost + ", ref=" + ref
+ "]";
}
}// foo
public static void main(String[] args) {
List<Foo> list = Arrays.asList(
new Foo(1, "P1", 300, 400), new Foo(2, "P2", 600, 400), new Foo(3, "P3", 30, 20),
new Foo(3, "P3", 70, 20), new Foo(1, "P1", 360, 40), new Foo(4, "P4", 320, 200),
new Foo(4, "P4", 500, 900)
);
// Method 1 :
Map<Integer, List<Foo>> collect = list.stream()
.collect(
Collectors.groupingBy(
Foo::getId,
Collectors.collectingAndThen(
Collectors.toList(),
Function.identity()
)// andthen
)// gr
);
System.out.println(collect);
/*
{
1=[ [id=1, targetCost=400, actualCost=300, ref=P1],
id=1, targetCost=40, actualCost=360, ref=P1]],
2=[ [id=2, targetCost=400, actualCost=600, ref=P2]],
3=[ [id=3, targetCost=20, actualCost=30, ref=P3],
[id=3, targetCost=20, actualCost=70, ref=P3]],
4=[ [id=4, targetCost=200, actualCost=320, ref=P4],
[id=4, targetCost=900, actualCost=500, ref=P4]]
}
*/
// Method 2
Map<Integer, List<Foo>> collect2 = list.stream().collect(
Collectors.groupingBy(
Foo::getId,
Collectors.mapping(
Function.identity(),
Collectors.toList())));
System.out.println(collect2);
/*
{
1=[ [id=1, targetCost=400, actualCost=300, ref=P1],
[id=1, targetCost=40, actualCost=360, ref=P1]],
2=[ [id=2, targetCost=400, actualCost=600, ref=P2]],
3=[ [id=3, targetCost=20, actualCost=30, ref=P3],
[id=3, targetCost=20, actualCost=70, ref=P3]],
4=[ [id=4, targetCost=200, actualCost=320, ref=P4],
[id=4, targetCost=900, actualCost=500, ref=P4]]
}
*/
// Method 3
// If you need to compare something the you can use Compare.comparing
Map<Integer, List<Foo>> collect3 = list
.stream()
.sorted( Comparator.comparing(Foo::getId)
.thenComparing(Foo::getActualCost)
.thenComparing(Foo::getTargetCost) )
.collect(
Collectors.groupingBy(ch -> ch.id)
);
System.out.println(collect3);
/*
{
1=[ [id=1, targetCost=400, actualCost=300, ref=P1],
[id=1, targetCost=40, actualCost=360, ref=P1]],
2=[ [id=2, targetCost=400, actualCost=600, ref=P2]],
3=[ [id=3, targetCost=20, actualCost=30, ref=P3],
[id=3, targetCost=20, actualCost=70, ref=P3]],
4=[ [id=4, targetCost=200, actualCost=320, ref=P4],
[id=4, targetCost=900, actualCost=500, ref=P4]]
}
*/
}// main
}