1

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.

3
  • what is current/previous direction and quantity in the MatchOrders class? Can you add a sample input and output to explain this? Commented Jul 29, 2019 at 13:03
  • 1
    I am having troubles fully understanding what do you need. If you wish to change the elements of your stream (for example - start from Stream<Order> and finish with Stream<MatchedOrder>, mapping is your friend, i.e.: map function, which requires you to specify how would you like to convert Order to MatchedOrder. Simple Input and Output would help immensely. Commented Jul 29, 2019 at 13:03
  • I suggest you first write it without streams to understand what operations you need in general. Then you can put these same operations in stream form, that should be very easy. Commented Jul 29, 2019 at 13:29

3 Answers 3

1

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());
Sign up to request clarification or add additional context in comments.

1 Comment

Oops, misremembered the findFirst API. Fixed now.
1

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());

Comments

0

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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.