2015-10-22 8 views
7

Я стараюсь познакомиться с лямбда-функциями. Для начала я решил написать удобный класс под названием TernaryOperator. Итак, вопрос в том, правильно ли я получил идеологию, или я что-то упускаю, так как это должно быть сделано по-другому?Является ли это правильным использованием функционального интерфейса?

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); 
    } 
} 

Я вижу использование этого класса, как это:

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); 

И теперь я могу вычислить длину любой строки, даже если он пустой с этим Oneliner.

Итак, если у вас есть идеи, как лучше писать TernaryOperator, или если вы считаете, что это бесполезно, сообщите мне.

+3

Ваш код в порядке. – Jesper

+3

Это лучше подходит для http://codereview.stackexchange.com/ –

ответ

6

Не нужно использовать интерфейс Function. Лучше написать статический метод в некотором соответствующем классе вместо:

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); 
} 

И использовать так:

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

рассмотреть также с помощью import static для утилиты класса и писать просто ternary(condition, ifTrue, ifFalse).

Возможно, такой способ может быть полезен в некоторых ситуациях. Особенно, когда вы можете использовать ссылки на методы. Например:

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

Но спросите себя, будет ли 'ternary (String :: isEmpty, x ->" none ", String :: trim)' действительно лучше, чем выражение 's -> s.isEmpty()? "none": s.trim() '... – Holger