Java 8+ stream: Check if list is in the correct order for two fields of my object-instances

Kevin Cruijssen :

The title may be a bit vague, but here is what I have (in privatized code):

A class with some fields, including a BigDecimal and Date:

class MyObj{
  private java.math.BigDecimal percentage;
  private java.util.Date date;
  // Some more irrelevant fields

  // Getters and Setters
}

In another class I have a list of these objects (i.e. java.util.List<MyObj> myList). What I want now is a Java 8 stream to check if the list is in the correct order of both dates and percentages for my validator.

For example, the following list would be truthy:

[ MyObj { percentage = 25, date = 01-01-2018 },
  MyObj { percentage = 50, date = 01-02-2018 },
  MyObj { percentage = 100, date = 15-04-2019 } ]

But this list would be falsey because the percentage aren't in the correct order:

[ MyObj { percentage = 25, date = 01-01-2018 },
  MyObj { percentage = 20, date = 01-02-2018 },
  MyObj { percentage = 100, date = 15-04-2019 } ]

And this list would also be falsey because the dates aren't in the correct order:

[ MyObj { percentage = 25, date = 10-03-2018 },
  MyObj { percentage = 50, date = 01-02-2018 },
  MyObj { percentage = 100, date = 15-04-2019 } ]

One possible solution might be creating Pairs like this and then using an ! and .anyMatch checking each individual Pair<MyObj>. But I don't really want to create a Pair class just for this purpose if possible.

Is there perhaps a way to use .reduce or something to loop over pairs of MyObj to check them? What would be the best approach here to check if all dates and percentages of the MyObj in my list are in the correct order using Java 8 stream?

Another possibility is perhaps sorting the list by date, and then checking if they are all in order of percentage, if that's easier than checking both fields are the same time. The same issue with comparing pairs of MyObj for the percentage still remains, though.

(PS: I will use it for a com.vaadin.server.SerializablePredicate<MyObj> validator, and I prefer a Java 8 lambda because I've also used some for the other validators, so it would be more in line with the rest of the code. The Java 8 lambda is more a preference than requirement in my question however.)

Eugene :

Well if you want a short-circuiting operation, I don't think an easy solution using stream-api exists... I propose a simpler one, first define a method that in a short-circuiting way will tell you if your List is sorted or not, based on some parameter:

 private static <T, R extends Comparable<? super R>> boolean isSorted(List<T> list, Function<T, R> f) {
    Comparator<T> comp = Comparator.comparing(f);
    for (int i = 0; i < list.size() - 1; ++i) {
        T left = list.get(i);
        T right = list.get(i + 1);
        if (comp.compare(left, right) >= 0) {
            return false;
        }
    }

    return true;
}

And calling it via:

 System.out.println(
          isSorted(myList, MyObj::getPercentage) && 
          isSorted(myList, MyObj::getDate));

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=35545&siteId=1