Reputation: 8487
Does Java8 could convenient to implement below requirement, that is
Map<X,Y> + Map<Y,Z> = Map<X,Z>
Now my code is
ArrayList<String> couponCodes = newArrayList("aaa", "bbb", "ccc");
// couponCode -- shopId
ArrayList<ShopCoupon> shopCoupons = newArrayList(new ShopCoupon("aaa", 1), new ShopCoupon("bbb", 2), new ShopCoupon("ccc", 3));
Map<String, Integer> couponCodeShopIdMap = shopCoupons.stream().collect(toMap(sc -> sc.getCouponCode(), sc -> sc.getShopId()));
// shopId -- name
ArrayList<Shop> shops = newArrayList(new Shop(1, "zhangsan"), new Shop(2, "lisi"), new Shop(3, "wangwu"));
Map<Integer, String> shopIdNameMap = shops.stream().collect(toMap(s -> s.getId(), s -> s.getName()));
//couponCode -- name
Map<String, String> couponCodeNameMap = couponCodes.stream().collect(toMap(c -> c, c -> shopIdNameMap.get(couponCodeShopIdMap.get(c))));
System.out.println(couponCodeNameMap);
I want to know is some more convenient manner to implement this requirement?
Upvotes: 3
Views: 307
Reputation: 9633
You can do simply using Default Methods of Map from Java 8
shopIdNameMap.forEach((key,value)->shopIdNameMap.replace(key,couponCodeNameMap.get(value)));
Upvotes: 0
Reputation: 93842
Another way would be to stream over the entry set of the first map directly, e.g:
public static <X, Y, Z> Map<X, Z> join(Map<X, Y> left, Map<Y, Z> right) {
return left.entrySet()
.stream()
.collect(toMap(Map.Entry::getKey, e -> right.get(e.getValue())));
}
The only thing you have to deal with is when a value is present in the left map and not the corresponding key in the right map, you'll have a NullPointerException
, since the value mapper function is not allowed to return null
. In this case you can either use getOrDefault
to provide a non-null default value to be associated with using e -> right.getOrDefault(e.getValue(), defaultValue)
, or if you don't want to have the mapping in the resulting map, mimick the toMap
collector by filtering upfront the inexistant mappings.
public static <X, Y, Z> Map<X, Z> join(Map<X, Y> left, Map<Y, Z> right) {
return left.entrySet().stream().collect(
HashMap::new,
(m, e) -> {
//if you still want the mapping k -> null,
//you can just use put directly
Z value = right.get(e.getValue());
if(value != null) m.put(e.getKey(), value);
},
Map::putAll);
}
Upvotes: 7