I've a list of Order which I am fetching from some third part api.
List<Order> orders = fromApi(orderId);
Here is the Order class:
class Order{
Long orderId;
Product product
}
Similarly I fetch products also for those orders. Here the key is orderId.
List<Order> orderIds = orders.stream().map(Order::orderId).collect(Collectors.toList());
Map<Long,Product> userProductMap = fromAnotherApi(orderIds);
Here is Product class:
class Product{
String productDesc;
}
I want to extract a map with orderId as a key and Order as value(given below), but meanwhile also want to update orders with the product(from userProductMap) in same stream iteration.
Map<Long,Order> userOrderMap = orders.stream().collect(Collectors.toMap(order -> order.id, Function.identity()));
I want to provide some custom implementation instead of Function.identity() so that while putting Order as value in Map here, I take out product from the userProductMap and update in Order and use updated Order in Map as value.
I’m not sure Streams are beneficial here, since you are modifying each Order as you add it to a Map. I would just use a loop:
Map<Long, Order> ordersById = new HashMap<>();
for (Order order : orders) {
Long orderId = order.getOrderId();
order.setProduct(userProductMap.get(orderId));
ordersById.put(orderId, order);
}
If you insist on doing it with a Stream, and if you have the ability to modify the Order class, you can add a chaining method that returns the object itself:
public class Order {
// [other fields and methods]
public Order withProduct(Product product) {
this.product = product;
return this;
}
}
which allows you to write this:
Map<Long, Order> ordersById = orders.stream()
.collect(Collectors.toMap(o -> o.getOrderId(),
o -> o.withProduct(userProductMap.get(o.getOrderId()))));
If you don’t have the ability to modify the Order class, but still insist on using a Stream, you probably need to fall back to using the peek
method:
Map<Long, Order> ordersById = orders.stream()
.peek(o -> o.setProduct(userProductMap.get(o.getOrderId())))
.collect(Collectors.toMap(o -> o.getOrderId(), o -> o));
This isn’t really what peek
is for, so I personally would opt for one of the other approaches.