Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: functional chaining of getters or zero args methods

I want to create Comparator based on Enum.name() which is inside a bean class:

List.of(new JobRsp(Job.MY), new JobRsp(Job.OUR), new JobRsp(Job.YOUR)).stream()
    .sorted(__ -> __.getJob().name());

If I only needed Enum.order() I could write sorted(Job::getJob).

Is it possible co compose zero args methods in functional style in Java? Something like:

FuncUtils.compose(Job::getJob, Enum::name)

Or probably even longer:

.sort(FuncUtils.chainGetters(ObjA::getB, ObjB::getC, ObjC::getD, ObjD::getE))

Imaginary chainGetters might check for nulls.

I understand that Java doesn't allow variadic generics so there should be chainGetters for each argument arity.

like image 702
gavenkoa Avatar asked Dec 04 '25 10:12

gavenkoa


1 Answers

You have the default andThen method in Function interface that lets you chain functions.

Unfortunately there is no "clean" way to achieve the result, because to call a default method on a method reference you need to assign it, or cast it.

For example:

import static java.util.Comparator.comparing;

Function<Job, Enum> getJob = Job::getJob;
...
   .sorted(comparing(getJob.andThen(Enum::name)))

Or:

   .sorted(comparing( ((Function<Job, Enum>) Job::getJob).andThen(Enum::name) ))

So, it's cleaner to use a lambda expression using Comparator.comparing to create the comparator:

...
   .sorted(comparing(j -> j.getJob().name()))

The compose utility method that you suggest could be also implemented with:

public static <A, B, C>  Function<A, C> compose(Function<A, B> first, Function<B, C> second) {
    return first.andThen(second);
}

So you could use:

.sorted(comparing( FuncUtils.compose(Job::getJob, Enum::name)))
like image 155
areus Avatar answered Dec 06 '25 22:12

areus