Predicado Java 8 interno que sempre retorna verdadeiro?

129

O Google Guava tem um predicado que sempre retornatrue . O Java 8 tem algo semelhante para isso Predicate? Eu sei que poderia usar (foo)->{return true;}, mas quero algo pré-fabricado, análogo Collections.emptySet().

Garret Wilson
fonte

Respostas:

162

Não há predicados sempre verdadeiros e sempre falsos integrados no Java 8. A maneira mais concisa de escrevê-los é

x -> true

e

x -> false

Compare estes com

Predicates.alwaysTrue() // Guava

e finalmente para uma classe interna anônima:

new Predicate<Object>() {
    public boolean test(Object x) {
        return true;
    }
}

Provavelmente, a razão pela qual o Guava possui esses predicados internos é que há uma enorme vantagem sintática de uma chamada de método estático sobre uma classe interna anônima. No Java 8, a sintaxe lambda é tão concisa que há uma desvantagem sintática na gravação de uma chamada de método estática.

Essa é apenas uma comparação sintática, no entanto. Provavelmente, há uma pequena vantagem de espaço se houver um único predicado sempre verdadeiro global, comparado às x -> trueocorrências espalhadas por várias classes, cada uma das quais criaria sua própria instância de predicado. É com isso que você está preocupado? As economias não pareciam convincentes, e é provavelmente por isso que não foram adicionadas em primeiro lugar. Mas poderia ser reconsiderado para uma versão futura.

ATUALIZAÇÃO 24-04-2015

Nós consideramos a adição de uma variedade de estática, chamados funções, tais como Predicate.alwaysTrue, Runnable.noop, etc., e decidimos não adicionar mais em futuras versões do Java SE.

Certamente, existe algum valor em algo que tem um nome versus um lambda gravado, mas esse valor é bem pequeno. Esperamos que as pessoas vão aprender a ler e escrever x -> truee () -> { }, e que seu uso se tornará idiomática. Até o valor do Function.identity()excesso x -> xé questionável.

Há uma pequena vantagem de desempenho em reutilizar uma função existente, em vez de avaliar um lambda gravado, mas esperamos que o uso desses tipos de funções seja tão pequeno que essa vantagem seja insignificante, certamente não vale o inchaço da API.

Holger também mencionou nos comentários a possibilidade de otimizar funções compostas como Predicate.oressas. Isso também foi considerado ( JDK-8067971 ), mas foi considerado um tanto frágil e suscetível a erros, ocorrendo com pouca frequência que não valeu a pena o esforço de implementação.

Veja também esta entrada das perguntas frequentes do Lambda .

Stuart Marks
fonte
14
Duas preocupações: a primeira é a brevidade. Se (foo)->{return true;}é o melhor que posso fazer, quero melhor. Mas você mencionou x->true, o que é muito melhor e atenua a primeira questão. A segunda questão é de lógica vs declaração estática. Se eu usar x->true, ainda há lógica envolvida, que eu poderia inadvertidamente estragar (por exemplo x->!true). Mas com Predicate.alwaysTrue(), não há espaço para erro lógico, pois existem apenas um ou dois métodos semelhantes. Além disso, recebo a conclusão do código IDE gratuitamente. x->trueestá quase bem, mas ainda escrevi um Predicate.alwaysTrue()método pelas razões acima.
Garret Wilson
10
@GarretWilson Mas com Predicate.alwaysTrue()você também pode estragar tudo acidentalmente escrevendo Predicate.alwaysFalse().
David Conrad
5
@DavidConrad, é claro. Sempre há maneiras de cometer erros e, na verdade, estou constantemente inventando novos. ;) Não quero iniciar uma discussão aqui sobre algo trivial, mas vou apenas dizer que meu argumento é que, com uma referência de método estático, tenho um vocabulário restrito com apenas duas opções: alwaysTrue()e alwaysFalse(). Com o lambda real, tenho muitas variações; Estou essencialmente reconstruindo a fórmula a cada vez. Em essência, alwaysTrue()é um rótulo semântico para o que eu quero fazer; x->trueestá realmente fazendo isso de novo a cada vez. Não é enorme, mas uma consideração.
Garret Wilson
25
Uma grande vantagem da Canonical Predicate.alwaysTrue()e Predicate.alwaysFalse()exemplos é que eles poderiam ser reconhecidos através da combinação de métodos como Predicate.or, Predicate.and, e Predicate.negate(). Isso permitiria pré-inicializar Predicatevariáveis ​​com alwaysTrue()e adicionar predicados combinando via andsem sobrecarga. Como as expressões lambda não têm garantia de identidade de objeto, isso pode falhar x->true. By the way, se eu tiver uma classe Xcom um staticmétodo y(){return true;}, usando X::yé ainda mais curto do que x->true, mas realmente não recomendado ...
Holger
10
O idioma x -> truetem a desvantagem de que eu tenho que usar uma variável sem uso. Isso cria carga cerebral desnecessária e também um aviso no meu IDE. Eu tentei usar _ -> true, mas isso é um erro de sintaxe. Definitivamente, falta a Java uma palavra-chave (leia-se: keyletter) para "parâmetro não utilizado". Esperança de que algo como isto virá em Java 9 (ou, pelo menos: Java qualquer que seja antes de morrer ^^)
kap
4

Sem goiaba

Boolean.TRUE::booleanValue
boriselec
fonte
3
Isso é interessante. Não tenho certeza se ele capta completamente o espírito da solicitação, mas ganha pontos pela criatividade!
Garret Wilson
21
Mas não é um Predicate, pois não é necessário um argumento.
Florent Guillaume
1
Não é um predicado, é uma referência de método, mas tem o mérito de ser conciso e não forçar a mencionar um parâmetro não utilizado. +1 By the way, uma vez que evita a utilização de goiaba, que tem um sério problema de modularidade, que merece o meu upvote;)
gouessej
16
A sua referência método é atribuível ao Fornecedor <Boolean>, mas não Predicate <T>
Daniel K.