问题
I have a List<Valuta>
which can be represented (simplified) JSON-style:
[ { codice=EUR, description=Euro, ratio=1 }, { codice=USD, description=Dollars, ratio=1.1 } ]
I want to transform that in a Map<String, Valuta>
like this:
{ EUR={ codice=EUR, description=Euro, ratio=1 }, USD={ codice=USD, description=Dollars, ratio=1.1 }}
I wrote this one-liner:
getValute().stream().collect(Collectors.groupingBy(Valuta::getCodice));
but this returns a Map<String, List<Valuta>>
instead of what I need.
I suppose mapping()
function would work for me, but don't know how.
回答1:
Actually, you need to use Collectors.toMap
here instead of Collectors.groupingBy
:
Map<String, Valuta> map =
getValute().stream()
.collect(Collectors.toMap(Valuta::getCodice, Function.identity()));
groupingBy is used to group elements of a Stream based on a grouping function. 2 Stream elements that will have the same result with the grouping function will be collected into a List
by default.
toMap will collect the elements into a Map
where the key is the result of applying a given key mapper and the value is the result of applying a value mapper. Note that toMap
, by default, will throw an exception if a duplicate is encountered.
回答2:
It's a bit late in the game, but try this:
Map<String, Valuta> map =
getValute().stream()
.collect(Collectors.groupingBy(Valuta::getCodice,
Collectors.collectingAndThen(
Collectors.toList(),
values -> values.get(0))));
回答3:
You could use Collectors.toMap(keyMappingFunction, valueMappingFunction)
Map<String, Valuta> map = list
.stream()
.collect(Collectors.toMap(Valuta::getCodice, v -> v));
You can replace v->v
with Function.identity()
if you find it more readable.
回答4:
Here are 3 methods.
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
}
来源:https://stackoverflow.com/questions/34495816/stream-groupingby-reducing-to-first-element-of-list