antonpp
antonpp

Reputation: 2373

Is this a proper usage of Function interface?

I am trying to get familiar with lambda functions. To start with I decided to write a handy class called TernaryOperator. So, the question is did I get the ideology right or am I missing something as it should be done in a different way?

public class TernaryOperator<T, U> implements Function<T, U> {

    private final Function<T, U> f;

    public TernaryOperator(Predicate<? super T> condition,
                           Function<? super T, ? extends U> ifTrue,
                           Function<? super T, ? extends U> ifFalse) {
        this.f = t -> condition.test(t) ? ifTrue.apply(t) : ifFalse.apply(t);
    }

    @Override
    public U apply(T t) {
        return f.apply(t);
    }
}

I see usage of this class like this:

Predicate<Object> condition = Objects::isNull;
Function<Object, Integer> ifTrue = obj -> 0;
Function<CharSequence, Integer> ifFalse = CharSequence::length;
Function<String, Integer> safeStringLength = new TernaryOperator<>(condition, ifTrue, ifFalse);

And now I can calculate a length of any string even if it is a null with this oneliner.

So, if you have any ideas how to write better TernaryOperator or if you think that it is useless, please tell me.

Upvotes: 7

Views: 1503

Answers (1)

Tagir Valeev
Tagir Valeev

Reputation: 100219

No need to implement the Function interface. It's better to write static method in some appropriate class instead:

public static <T, U> Function<T, U> ternary(Predicate<? super T> condition,
                       Function<? super T, ? extends U> ifTrue,
                       Function<? super T, ? extends U> ifFalse) {
    return t -> condition.test(t) ? ifTrue.apply(t) : ifFalse.apply(t);
}

And use like this:

Function<String, Integer> safeStringLength = MyClass.ternary(condition, ifTrue, ifFalse);

Also consider using import static for your utility class and write simply ternary(condition, ifTrue, ifFalse).

Probably such method could be useful in some situations. Especially when you can use method references. For example:

Stream.of(strings).map(ternary(String::isEmpty, x -> "none", String::trim))...

Upvotes: 7

Related Questions