java JAVA8 - 使用 lambda 进行分组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25244181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JAVA8 - Grouping with lambda
提问by Lukas Novicky
I have a collection with structure like this:
我有一个结构如下的集合:
@Entity
public class RRR{
private Map<XClas, YClas> xySets;
}
and XClas
has a field called ZZZ
并且XClas
有一个字段叫做ZZZ
my question is:
I would like to aggregate it with lambda to get a Map<ZZZ, List<RRR>>
.
我的问题是:我想将它与 lambda 聚合以获得Map<ZZZ, List<RRR>>
.
Is it possible? Now I'm stuck with:
是否可以?现在我坚持:
Map xxx = rrrList.stream().collect(
Collectors.groupingBy(x->x.xySets().entrySet().stream().collect(
Collectors.groupingBy(y->y.getKey().getZZZ()))));
but it's Map<Map<ZZZ, List<XClas>>, List<RRR>>
so it's not what I was looking for :)
但这Map<Map<ZZZ, List<XClas>>, List<RRR>>
不是我想要的:)
Right now just to make it work, I did aggregation with two nested loops, but it would be so great, if you could help me make it done with lambdas.
现在只是为了让它工作,我用两个嵌套循环进行了聚合,但是如果你能帮我用 lambda 来完成它,那就太好了。
EDIT
编辑
I post what I got by now, as asked. I already left nested loops, and I manage to work my way up to this point:
我发布了我现在得到的东西,正如所问的那样。我已经离开了嵌套循环,并且我设法做到了这一点:
Map<ZZZ, List<RRR>> temp;
rrrList.stream().forEach(x -> x.getxySetsAsList().stream().forEach(z -> {
if (temp.containsKey(z.getKey().getZZZ())){
List<RRR> uuu = new LinkedList<>(temp.get(z.getKey().getZZZ()));
uuu.add(x);
temp.put(z.getKey().getZZZ(), uuu);
} else {
temp.put(z.getKey().getZZZ(), Collections.singletonList(x));
}
}));
Thanks in advance
提前致谢
采纳答案by halfbit
I have tried around a bit and found the following solution, posting it here just as another example:
我尝试了一些并找到了以下解决方案,将其发布在此处作为另一个示例:
rrrList.stream().map(x -> x.xySets).map(Map::entrySet).flatMap(x -> x.stream())
.collect(Collectors.groupingBy(x -> x.getKey().getZZZ(),
Collectors.mapping(Entry::getValue, Collectors.toList())));
The first line could also be written as rrrList.stream().flatMap(x -> x.xySets.entrySet().stream())
which might be found more readable.
Here is self-contained example code for those wanting to play around themselves:
第一行也可以写成rrrList.stream().flatMap(x -> x.xySets.entrySet().stream())
这样可能更易读。以下是那些想要玩弄自己的人的自包含示例代码:
public static void main(String[] args) {
List<RRR> rrrList = Arrays.asList(new RRR(), new RRR(), new RRR());
System.out.println(rrrList);
Stream<Entry<XClas, YClas>> sf = rrrList.stream().map(x -> x.xySets).map(Map::entrySet).flatMap(x -> x.stream());
Map<ZZZ, List<YClas>> res = sf.collect(Collectors.groupingBy(x -> x.getKey().getZZZ(), Collectors.mapping(Entry::getValue, Collectors.toList())));
System.out.println(res);
}
public static class RRR {
static XClas shared = new XClas();
private Map<XClas, YClas> xySets = new HashMap<>();
RRR() { xySets.put(shared, new YClas()); xySets.put(new XClas(), new YClas()); }
static int s = 0; int n = s++;
public String toString() { return "RRR" + n + "(" + xySets + ")"; }
}
public static class XClas {
private ZZZ zzz = new ZZZ();
public ZZZ getZZZ() { return zzz; }
public String toString() { return "XClas(" + zzz + ")"; }
public boolean equals(Object o) { return (o instanceof XClas) && ((XClas)o).zzz.equals(zzz); }
public int hashCode() { return zzz.hashCode(); }
}
public static class YClas {
static int s = 0; int n = s++;
public String toString() { return "YClas" + n; }
}
public static class ZZZ {
static int s = 0; int n = s++ / 2;
public String toString() { return "ZZZ" + n; }
public boolean equals(Object o) { return (o instanceof ZZZ) && ((ZZZ)o).n == n; }
public int hashCode() { return n; }
}
回答by korda
Something like that? :
类似的东西?:
Map<ZZZ, List<RRR>> map = new HashMap<>();
list.stream().forEach(rrr -> {
rrr.xySets.keySet().stream().forEach(xclas -> {
if (!map.containsKey(xclas.zzz))
map.put(xclas.zzz, new ArrayList<RRR>());
map.get(xclas.zzz).add(rrr);
});
});
回答by Alex
Another way you could do this:
另一种方法可以做到这一点:
Map<Z, List<R>> map = rs.stream()
.map(r -> r.xys.keySet()
.stream()
.collect(Collectors.<X, Z, R>toMap(x -> x.z, x -> r, (a, b) -> a)))
.map(Map::entrySet)
.flatMap(Collection::stream)
.collect(Collectors.groupingBy(Entry::getKey,
Collectors.mapping(Entry::getValue, Collectors.toList())));