NSN
NSN

Reputation: 750

Convert to List<AnotherObject> from List<Object>,List<Object> using streams Java 8

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

Answers (3)

jacobm
jacobm

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

eham
eham

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

Naman
Naman

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

Related Questions