У меня есть список заказов, который я получаю из какого-то третьего API.
List<Order> orders = fromApi(orderId);
Вот класс Order:
class Order{
Long orderId;
Product product
}
Точно так же я приношу продукты и для этих заказов. Здесь ключом является orderId.
List<Order> orderIds = orders.stream().map(Order::orderId).collect(Collectors.toList());
Map<Long,Product> userProductMap = fromAnotherApi(orderIds);
Вот класс продукта:
class Product{
String productDesc;
}
Я хочу извлечь карту с orderId в качестве ключа и Order в качестве значения (указанного ниже), но в то же время я также хочу обновить заказы с помощью продукта (из userProductMap) в той же итерации потока.
Map<Long,Order> userOrderMap = orders.stream().collect(Collectors.toMap(order -> order.id, Function.identity()));
Я хочу предоставить некоторую пользовательскую реализацию вместо Function.identity(), чтобы, помещая здесь Order в качестве значения в Map, я извлекал продукт из userProductMap, обновлял в Order и использовал обновленный Order в Map в качестве значения.
Я только что обновил, это orderId, а не userId.
Если вы получаете userProductMap, передавая один идентификатор orderId в fromAnotherApi, тогда наверняка все продукты в возвращаемой карте предназначены только для одного заказа. (Хотя я признаю, что мне не совсем понятно, что означают длинные ключи в userProductMap.)
Вместо Function.identity()
вы можете ссылаться на любой метод, который принимает Order
в качестве параметра и возвращает Order
. Просто напишите такой метод, который делает с переданным Order
все, что захотите.
какой ключ в userProductMap
?
@VGR только что обновил код.
@cyberbrain Я обновляю код для большей ясности.
вы не ответили на мой вопрос: какой ключ в userProductMap
- есть Long
из вызова API, но вы не сказали нам, например, это ли это. идентификатор продукта или что-то совершенно другое. Кроме того, слово «пользователь» в названиях ваших карт меня немного смущает: есть ли где-нибудь задействованный пользователь (я имею в виду код, а не то, что пользователь может запускать все это)?
Ключ @cyberbrain для userProductMap — это orderId. и Эта карта приходит как ответ от другого API. «Аналогично я получаю продукты и для этих заказов. Здесь ключ — orderId».
извини, перечитал.
Поскольку ваш Product
имеет только описание в качестве элемента, как вы узнаете, какие продукты являются «новыми», но связаны со старым продуктом, который вы хотите заменить? Есть ли внутри продукта также идентификатор? Какая-то внешняя функция, которая может определить, являются ли два экземпляра продукта одинаковыми в бизнес-представлении, даже если они находятся в разных объектах?
@cyberbrain предположим, что на моей стороне у продукта на данный момент нет идентификатора. Это сопоставление исходит из другого API, на данный момент мы можем избежать этого идентификатора продукта.
Итак, вам нужно объяснить, как можно «извлечь продукт из userProductMap, обновить его в Order и использовать обновленный Order в Map в качестве значения». - как связать товар из заказа с обновленным товаром из userProductMap
?
Я не уверен, что потоки здесь полезны, поскольку вы изменяете каждый заказ при добавлении его на карту. Я бы просто использовал цикл:
Map<Long, Order> ordersById = new HashMap<>();
for (Order order : orders) {
Long orderId = order.getOrderId();
order.setProduct(userProductMap.get(orderId));
ordersById.put(orderId, order);
}
Если вы настаиваете на том, чтобы сделать это с помощью Stream, и если у вас есть возможность изменить класс Order, вы можете добавить метод цепочки, который возвращает сам объект:
public class Order {
// [other fields and methods]
public Order withProduct(Product product) {
this.product = product;
return this;
}
}
что позволяет вам написать это:
Map<Long, Order> ordersById = orders.stream()
.collect(Collectors.toMap(o -> o.getOrderId(),
o -> o.withProduct(userProductMap.get(o.getOrderId()))));
Если у вас нет возможности изменять класс Order, но вы все равно настаиваете на использовании Stream, вам, вероятно, придется вернуться к использованию метода peek
:
Map<Long, Order> ordersById = orders.stream()
.peek(o -> o.setProduct(userProductMap.get(o.getOrderId())))
.collect(Collectors.toMap(o -> o.getOrderId(), o -> o));
На самом деле это не для чего нужен просмотр, поэтому лично я бы выбрал один из других подходов.
какой идентификатор пользователя? Ни ваш
Order
, ни вашProduct
не содержат того, что соответствует вашему описанию.