A minha opinião é usar um unário +
para acionar o unboxing de um dos operandos ao verificar a igualdade de valor e simplesmente usar os operadores matemáticos. A justificativa a seguir:
Já foi mencionado que ==
comparação para Integer
é comparação de identidade, o que geralmente não é o que um programador deseja e que o objetivo é fazer comparação de valor; Ainda assim, eu fiz um pouco de ciência sobre como fazer essa comparação com mais eficiência, tanto em termos de compactação de código, correção e velocidade.
Eu usei o monte de métodos usual:
public boolean method1() {
Integer i1 = 7, i2 = 5;
return i1.equals( i2 );
}
public boolean method2() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2.intValue();
}
public boolean method3() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2;
}
public boolean method4() {
Integer i1 = 7, i2 = 5;
return i1 == +i2;
}
public boolean method5() { // obviously not what we want..
Integer i1 = 7, i2 = 5;
return i1 == i2;
}
e obteve esse código após a compilação e descompilação:
public boolean method1() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
return var1.equals( var2 );
}
public boolean method2() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method3() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method4() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method5() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2 == var1 ) {
return true;
} else {
return false;
}
}
Como você pode ver facilmente, o método 1 chama Integer.equals()
(obviamente), os métodos 2-4 resultam exatamente no mesmo código , desembrulhando os valores por meio de.intValue()
e comparando-os diretamente, e o método 5 apenas aciona uma comparação de identidade, sendo a maneira incorreta de comparar valores.
Como (como já mencionado por exemplo, JS) equals()
incorre em uma sobrecarga (é necessário fazer instanceof
e uma conversão não verificada), os métodos 2 a 4 funcionam exatamente com a mesma velocidade, notavelmente melhor que o método 1 quando usado em loops apertados, já que o HotSpot não é provável otimizar os elencos & instanceof
.
É bem parecido com outros operadores de comparação (por exemplo, <
/ >
) - eles acionam o unboxing, enquanto o uso compareTo()
não - mas desta vez, a operação é altamente otimizável pelo HS, poisintValue()
é apenas um método getter (principal candidato a ser otimizado).
Na minha opinião, a versão 4 raramente usada é a maneira mais concisa - todo desenvolvedor experiente de C / Java sabe que o unary plus é na maioria dos casos igual a convertido para int
/ .intValue()
- embora possa ser um pouco WTF para alguns (principalmente aqueles que não usar o unário mais durante a vida útil), mostra sem dúvida a intenção de maneira mais clara e concisa - mostra que queremos um int
valor de um dos operandos, forçando o outro valor a desmarcar também. Também é indiscutivelmente o mais semelhante à i1 == i2
comparação regular usada para int
valores primitivos .
Meu voto é para i1 == +i2
& i1 > i2
style para Integer
objetos, tanto por questões de desempenho quanto de consistência. Também torna o código portável para primitivas sem alterar nada além da declaração de tipo. Usar métodos nomeados parece introduzir ruído semântico para mim, semelhante ao bigInt.add(10).multiply(-3)
estilo muito criticado .