我的同事出现了一个有趣的问题,我无法找到一个整洁而漂亮的
Java 8解决方案.问题是流过POJO列表,然后根据多个属性将它们收集到地图中 – 映射会导致POJO多次发生
想象一下POJO:
private static class Customer {
public String first;
public String last;
public Customer(String first, String last) {
this.first = first;
this.last = last;
}
public String toString() {
return "Customer(" + first + " " + last + ")";
}
}
将其设置为列表:
// The list of customers
List customers = Arrays.asList(
new Customer("Johnny", "Puma"),
new Customer("Super", "Mac"));
备选方案1:在“流”之外使用地图(或者外部forEach).
// Alt 1: not pretty since the resulting map is "outside" of
// the stream. If parallel streams are used it must be
// ConcurrentHashMap
Map res1 = new HashMap<>();
customers.stream().forEach(c -> {
res1.put(c.first, c);
res1.put(c.last, c);
});
备选方案2:创建地图条目并将其流式传输,然后对其进行平面化. IMO它有点太冗长了,不是那么容易阅读.
// Alt 2: A bit verbose and "new AbstractMap.SimpleEntry" feels as
// a "hard" dependency to AbstractMap
Map res2 =
customers.stream()
.map(p -> {
Map.Entry firstEntry = new AbstractMap.SimpleEntry<>(p.first, p);
Map.Entry lastEntry = new AbstractMap.SimpleEntry<>(p.last, p);
return Stream.of(firstEntry, lastEntry);
})
.flatMap(Function.identity())
.collect(Collectors.toMap(
Map.Entry::getKey, Map.Entry::getValue));
替代3:这是另一个,我提出了“最漂亮”代码到目前为止,但它使用三参数版本的减少和第三个参数是一个有点狡猾的发现在这个问题:Purpose of third argument to ‘reduce’ function in Java 8 functional programming.此外,减少不似乎很适合这个问题,因为它是突变,并行流可能无法使用下面的方法.
// Alt 3: using reduce. Not so pretty
Map res3 = customers.stream().reduce(
new HashMap<>(),
(m, p) -> {
m.put(p.first, p);
m.put(p.last, p);
return m;
}, (m1, m2) -> m2 /*
如果上面的代码打印如下:
System.out.println(res1);
System.out.println(res2);
System.out.println(res3);
结果是:
{Super=Customer(Super Mac), Johnny=Customer(Johnny Puma), Mac=Customer(Super Mac), Puma=Customer(Johnny Puma)}
{Super=Customer(Super Mac), Johnny=Customer(Johnny Puma), Mac=Customer(Super Mac), Puma=Customer(Johnny Puma)}
{Super=Customer(Super Mac), Johnny=Customer(Johnny Puma), Mac=Customer(Super Mac), Puma=Customer(Johnny Puma)}
所以,现在我的问题:我应该如何以Java 8有序的方式流经List< Customer>然后以某种方式收集它作为Map< String,Customer>您将整个事物分为两个键(第一个和最后一个),即客户映射两次.我不想使用任何第三方图书馆,我不想在alt之外使用流图之外的地图.还有其他很好的选择吗?
完整的代码可以是found on hastebin,用于简单的复制粘贴,以使整个事情运行.