Guava - Functions & Predicates

AVISO

O uso extensivo do idioma funcional que o Guava provê, torna o código verboso, confuso, ilegível e ineficiente. Com o abuso você vai ter código de uma linha, sendo essa extremamente longa.
Function<String, Integer> lengthFunction = new Function<String, Integer>() {
  public Integer apply(String string) {
    return string.length();
  }
};
Predicate<String> allCaps = new Predicate<String>() {
  public boolean apply(String string) {
    return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);
  }
};
Multiset<Integer> lengths = HashMultiset.create(
  Iterables.transform(Iterables.filter(strings, allCaps), lengthFunction));

Compare esse código

Com esse

Multiset<Integer> lengths = HashMultiset.create(
  FluentIterable.from(strings)
    .filter(new Predicate<String>() {
       public boolean apply(String string) {
         return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);
       }
     })
    .transform(new Function<String, Integer>() {
       public Integer apply(String string) {
         return string.length();
       }
     }));

Com esse

Multiset<Integer> lengths = HashMultiset.create();
for (String string : strings) {
  if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string)) {
    lengths.add(string.length());
  }
}
Código imperativo deve ser o seu padrão!
Você não deve usar expressões funcionais, a menos que você esteja absolutamente certo de uma das seguintes questões
O uso de expressões idiomáticas funcionais irá resultar em uma economia líquida de linhas de código para o projeto inteiro.

No exemplo anterior, a versão "funcional" usava 11 linhas, enquanto a versão imperativa apenas 6 linhas.

Já vimos que mover a definição de uma função para outro arquivo, ou uma constante, não nos ajuda.

Para a eficiência, você precisa ter uma lazily computed view da coleção transformada e não pode se contentar com uma coleção explicitamente computada.

Além disso, você já leu e releu Effective Java, item 55 (otimize criteriosamente), e além de seguir essas instruções, você tem realmente feito de benchmarking para provar que esta versão é mais rápido, e pode-se citar números para provar isso.

Interfaces Funcionais

Function <A, B>, que tem o único método (sem efeitos colaterais).
 B apply (A input). 
e para ser coerente com equals(), ou seja,

a.equals (b) implica que Function.apply(a).equals(Function.apply(b)).

Interfaces Funcionais

Predicate <A, B>, que tem o único método
 boolean apply(A input)

Function

Pode ser usada para executar uma determinada ação (função) em objetos

Isso é utilizado para alterar coleções em coleções de outro tipo

Function

Seu uso principal com o método transform() das classes Collections2, Iterables, Lists, Iterators e etc.

A classe Functions tem varios funções prontas e permite compor novas funções mais complexas

Predicate

Predicate checa se a condição é satisfeita pelo objeto passado.

Usada principalmente para filtrar coleções usando método filter() das classes Collections2, Iterables, Lists, Iterators e etc.

Predicate

Usada também para verificar se todos os elementos de uma coleção satisfazem a uma condição. ex: Iterables.all()

A classe Predicates tem varios funções prontas e permite compor novas funções mais complexas

Duvidas?

Made with Slides.com