This is my code
List<Integer> ints = Stream.of(1,2,4,3,5).collect(Collectors.toList());
Integer maxInt = ints.stream()
.max(Comparator.comparing(i -> i))
.get();
System.out.println("Maximum number in the set is " + maxInt);
output:
Maximum number in the set is 5
I cannot make distingues between two i
in below section of my code
Comparator.comparing(i -> i)
can anyone be kind and explain the difference between two i
?
The method
Comparator.comparing(…)
is intended to create aComparator
which uses an order based on a property of the objects to compare. When using the lambda expressioni -> i
, which is a short writing for(int i) -> { return i; }
here, as a property provider function, the resultingComparator
will compare the values itself. This works when the objects to compare have a natural order asInteger
has.So
does the same as
though the latter is more efficient as it is implemented as singleton for all types which have a natural order (and implement
Comparable
).The reason why
max
requires aComparator
at all, is because you are using the generic classStream
which might contain arbitrary objects.This allows, e.g. to use it like
streamOfPoints.max(Comparator.comparing(p->p.x))
to find the point with the largestx
value whilePoint
itself does not have a natural order. Or do something likestreamOfPersons.sorted(Comparator.comparing(Person::getAge))
.When using the specialized
IntStream
you can use the natural order directly which is likely to be more efficient:To illustrate the difference between “natural order” and a property based order:
this will print
as the natural order of
String
s is the lexicographical order wherez
is greater thanb
which is greater thana
On the other hand
will print
as
aaa
has the maximum length of allString
s in the stream. This is the intended use case forComparator.comparing
which can be made even more readable when using method references, i.e.Comparator.comparing(String::length)
which almost speaks for itself…Comparator.comparing
expects a function which maps the source object to the value which actually gets compared - in your case, as you don't want to pre-process the value to be compared,i
is simply mapped to itself.This function (note
->
is for closures and not to be confused with=>
which is for comparison)just means you need to compare the entire object as it is. i.e. if I have an
i
you need to comparei
A less trivial example might be
which will give you the minimum or
gives you a value which is farthest from 100.
which will give you the maximum comparing as a String i.e. "9" > "10" as a string.