How to find max key with some conditions in HashMap using Java 8 / Streams?

Viewed 765

Suppose I have following data :

enter image description here

Question :

  1. I want to find zscore of largest orderId where Pair is 'AB', OrderType is 'Buy' and status is 'InProgress'.

NOTE: I stored this data into HashMap name is orderBook where Key is orderId and Value is OrderModel (PairName, OrderType, Status, zscore).

Solution 1 :

    int maxOrderId = 0 ;
        getOrderBook().entrySet().stream()
                                .filter(e -> e.getValue().getPairName().equals("AB")
                                        && e.getValue().getCompletedStatus().equals("InProgress")
                                        && e.getValue().getOrderType().equals("Buy"))
                                .forEach(o -> {
                                    if (maxOrderId < o.getKey()) {
                                        maxOrderId = o.getKey();
                                    }
                                });
        
        double zscore = getOrderBook().get(maxOrderId).getzScore();
       System.out.println("Order ID :"+ maxOrderId +", Zscore :"+zscore);

output : Order ID : 5, Zscore : -2.5

I can find zscore using above code but I want to find in one go.

So How can I find the zscore of largest OrderId using Java 8 / streams in one line ?

Is there any better way than my code ?

3 Answers

What you're looking for is the max method:

Optional<Entry<Long,Order>> maxIdEntry = getOrderBook()
  .entrySet()
  .stream()
  .filter(/* your filter logic */)
  .max(Comparator.comparing(Entry::getKey));

This yields an Optional, so either use the isPresent() and get() methods or the ifPresent(Consumer<T> consumer) method for processing the result

You can use max() using Comparator to get largest OrderId and use map of Optional to map zScore .

double zscore = getOrderBook()
          .entrySet()
          .stream()
          .filter(e -> e.getValue().getPairName().equals("AB")
                      && e.getValue().getCompletedStatus().equals("InProgress")
                      && e.getValue().getOrderType().equals("Buy"))
          .max(Comparator.comparing(Entry::getKey))
          .map(e -> e.getValue().getzScore())
          .orElse(0);

The already existing answer are excellent. There are more ways:

How about using TreeMap which is able to keep the keys sorted? As long as the key is ex. a String, you don't even need to pass a Comparator.

// create a copy of HashMap as a TreeMap
NavigableMap<String, Order> navigableMap = new TreeMap<>(getOrderBook());

// remove unwanted entries (inverted condition)
navigableMap.entrySet().removeIf(e ->
     !e.getValue().getPairName().equals("AB") ||
     !e.getValue().getCompletedStatus().equals("InProgress") ||
     !e.getValue().getOrderType().equals("Buy"));

// NavigableMap::lastEntry gets an entry with the highest key (by the comparator)
double zscore = sortedMap.lastEntry().getValue().getzScore();
Related