2

I'm pretty new to Java streams. I've to split a string returned by filter in stream, create a new object with the strings in the split and compare each object with a predefined object. Stream looks like this (I know this is incorrect, just a representation of what I am trying to do):

xmlstream.stream()
         .filter(xml->xml.getName()) //returns a string
         .map(returnedString -> split("__"))
         .map(eachStringInList -> new TestObj(returnedStr[0], returnedStr[1]))
         .map(eachTestObj -> eachTestObj.compareTo(givenObj))
         .max(Comparing.compare(returnedObj :: aProperty))

How do I achieve this? Basically map each string in list to create an object, compare that to a fix object and return max based on one of the properties. Thanks.

1
  • If you need to find max between objects equal to givenObj than streams have filter functionality filter(obj -> obj.equals(givenObj)). After that stream will contain only objects that are equal to givenObj Commented Apr 26, 2018 at 20:45

1 Answer 1

2

You could use reduce like so:

TestObj predefined = ...

TestObj max = 
       xmlstream.stream()
                .map(xml -> xml.getName()) //returns a string
                .map(s -> s.split("__"))
                .map(a -> new TestObj(a[0], a[1]))
                .reduce(predifined, (e, a) -> 
                      e.aProperty().compareTo(a.aProperty()) >= 0 ? e : a);

A more efficient version of the above would be:

TestObj predefined = ...
TestObj max =
        xmlstream.stream()
                 .map(xml -> xml.getName()) //returns a string
                 .map(s -> s.split("__"))
                 .map(a -> new TestObj(a[0], a[1]))
                 .filter(e -> e.aProperty().compareTo(predefined.aProperty()) > 0)
                 .findFirst()
                 .orElse(predefined);

Update:

if you want to retrieve the max object by a given property from all the TestObj objects less than the predefined TestObj, then you can proceed as follows:

TestObj predefined = ...
Optional<TestObj> max =
             xmlstream.stream()
                      .map(xml -> xml.getName()) 
                      .map(s -> s.split("_"))
                      .map(a -> new TestObj(a[0], a[1]))
                      .filter(e -> e.aProperty().compareTo(predefined.aProperty()) < 0)
                      .max(Comparator.comparing(TestObj::aProperty));

max returns an Optional<T>; if you're unfamiliar with it then consult the documentation here to familiarise you're with the different ways to unwrap an Optional<T> object.

Sign up to request clarification or add additional context in comments.

5 Comments

Won't findFirst return the first object less than predefinedObject? I want the max of all the matches. The incoming stream is not sorted. Nevertheless, this looks like the correct solution, if I use max.
No, the findFirst will get the first object where the aProperty() is greater than predefined.aProperty() otherwise we return predefined, that's what the second code snippet does. what do you mean I want the max of all the matches?
So, if I find 3 objects less than the predefined object, I want to find the object that is greatest among all the matches. Example: compare returns following objects less than predefined: a_1, a_2, a_3. I need a_3. Findfirst may return a_1, correct?
@Maxsteel if I am not mistaken, you want the max object of all the objects less than the predefined object?
Thanks for putting the efforts to answer this accurately and clearly. Much appreciated! :)

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.