我的一位同事向我提出了一个有趣的问题,但是我找不到一个整洁漂亮的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 + ")";
}
}
将其设置为List:
// The list of customers
List customers = Arrays.asList(
new Customer("Johnny", "Puma"),
new Customer("Super", "Mac"));
备选方案1 :Map在“ stream”之外(或在之外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 :创建地图项并流式传输,然后流式传输flatMap。海事组织,这有点太冗长,不太容易阅读。
// 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
:到目前为止,这是我提出的“最精美”代码的另一种方案,但是它使用的三参数版本,reduce并且第三个参数在此问题中有点模糊:第三个参数用于“减少”的目的Java
8函数编程中的函数。此外,reduce由于它正在变异并且并行流可能不适用于以下方法,因此似乎不太适合此问题。
// 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 =客户(Super Mac),Johnny =客户(Johnny Puma),Mac = Customer(Super Mac),Puma
= Customer(Johnny Puma)}
{Super = Customer(Super Mac),Johnny = Customer(Johnny Puma), Mac
=客户(超级Mac),彪马=客户(约翰尼·彪马)}
{超级=客户(超级Mac),约翰尼=客户(约翰尼·彪马),Mac =客户(超级Mac),彪马=客户(约翰尼·彪马)}
所以,现在我的问题是:我应该如何以Java 8有序的方式流经List,然后以某种方式收集它,Map
Customer>将整个事物拆分为两个键(firstAND last),即Customer映射两次。我不想使用任何第三方库,也不想像alt
1一样在流之外使用地图。还有其他不错的选择吗?
完整的代码可以在hastebin上找到,以进行简单的复制粘贴以使整个过程正常运行。