Reputation: 750
I have 2 List of the same type say
class Orders {
Strig User;
String tradeDate;
BigDecimal Qty;
}
and after comparison, I want to convert to list of another object say
class DiffOrders {
String User;
String tradeDate;
BigDecimal currentQty;
BigDecimal prevQty;
}
I have two lists of Orders
List<Orders>currentOrders;
List<Orders>prevOrders;
List<Orders> DiffOrders = current.stream()
.filter(curr->previous.stream().anyMatch(prev->OrderPredicate.orderDiffSize(curr, prev)))
.collect(Collectors.toList());
For orders on the same date and for the same user I want to capture the quantity in the matching order.
I am able to find the List<Orders>
that matched. But not sure how to capture and convert to the List<DiffOrders>
of new Class. Could you please help?
edit 1: OrderPredicate.orderDiffSize is a simple function that compares the user, trade date, quantity, and sign (+ for sell, - for buy) for the current and previous order. Not provided here for brevity.
edit 2: The size of the prev/current list is reasonable and can ignore o log n computation issues.
edit 3: Removed direction to keep it simple. For eg, I have orders in prevOrders and CurrentOrders on 01-Jul, 02-Jul, 03-Jul respectively. If the order quantity is different for the same date I want to put it in DiffOrders with quantity from current and previous. Hope this makes it clear.
Upvotes: 1
Views: 125
Reputation: 14035
Sounds like the crux of this problem is that you want to omit any items in current
that don't have matches in previous
, but transform items that do have matches using the actual corresponding value from previous
. In that case flatMap
is what you want. You can use flatMap
to transform each Order
not into a DiffOrders
, but into a stream of DiffOrders
that will be empty for non-matches and consist of a single element for matches.
List<DiffOrders> matchedOrders = current.stream()
.flatMap(curr -> {
Optional<Order> p = previous.stream()
.filter(prev -> OrderPredicate.orderSameDirectionAndSize(curr, prev))
.findFirst();
if (p.isPresent() && !p.get().qty.equals(curr.qty)) {
return Stream.of(new DiffOrders(curr.user, curr.tradeDate, curr.qty, p.get().qty));
} else {
return Stream.empty();
}
})
.collect(Collectors.toList());
Upvotes: 1
Reputation: 1
for simple code and easy algorithm in two steps it can be resolved;
private List<DiffOrders> mergeLists(List<Orders> currentOrders, List<Orders> prevOrders) {
Map<String, List<Orders>> map = prevOrders.stream().collect(Collectors.groupingBy(order -> order.getUser() + order.getTradeDate()));
return currentOrders.stream().filter(current ->{
String key = current.getUser() + current.getTradeDate();
return map.get(key) != null && !map.get(key).isEmpty();
}).map(current -> mapper(current, map.get(current.getUser() + current.getTradeDate()))).collect(Collectors.toList());
}
private DiffOrders mapper(Orders current, List<Orders> list) {
DiffOrders diffOrders = new DiffOrders();
diffOrders.setCurrentQty(current.getQty());
diffOrders.setTradeDate(current.getTradeDate());
diffOrders.setUser(current.getUser());
diffOrders.setPrevQty(list.get(0).getQty());
return diffOrders;
}
Upvotes: 0
Reputation: 32036
One of the primary need from the question as I understand is the mapping of current and previous Order
, so that you can construct the MatchOrder
out of the details. Ofcourse, this will require a map
operation along with the filter
during the construction of the such current to previous entries.
List<MatchOrders> matchedOrders = currentOrders.stream()
.map(curr -> new AbstractMap.SimpleEntry<>(curr, prevOrders.stream()
.filter(prev -> orderSameDirectionAndSize(curr, prev))
.findAny())) // <Order, Optional<Order>> currentToOptionalPrevious
.map(e -> {
Orders current = e.getKey();
Orders previous = e.getValue().orElse(current); // assumed a fallback
return new MatchOrders(current.getUser(), current.getQty(),
previous.getQty(), current.getDirection(), previous.getDirection());
})
.collect(Collectors.toList());
Upvotes: 1