java - gui - jtextfield hint
Forma abreviada para la declaraciĆ³n Java If Else (10)
Dado que el propósito real de la función parece ser manejar objetos no null
al hacer coincidirlos, manejaría todas las comprobaciones null
en una declaración de guardia al principio.
Luego, una vez que haya establecido que ningún argumento es null
, puede manejar la lógica real:
private int similarityCount(String a, String b) {
if (a == null || b == null) {
return a == b ? 1 : a == null ? 2 : 3;
}
return isMatch(a, b) ? 4 : 5;
}
Esto es más conciso y más legible que las otras opciones.
Dicho esto, las funciones reales generalmente no devolverían dichos códigos numéricos. A menos que se simplifique su método para ejemplificar el problema, le recomiendo encarecidamente que reconsidere la lógica y escriba algo similar a lo que sigue a continuación:
private boolean similarityCount(String a, String b) {
if (a == null || b == null) {
throw new NullPointerException();
}
return isMatch(a, b);
}
O:
private boolean similarityCount(String a, String b) {
if (a == null) {
throw new IllegalArgumentException("a");
}
if (b == null) {
throw new IllegalArgumentException("b");
}
return isMatch(a, b);
}
Estos enfoques serían más convencionales. Por otro lado, pueden desencadenar una excepción. Podemos evitar esto devolviendo un java.util.Optional<Boolean>
en Java 8:
private Optional<Boolean> similarityCount(String a, String b) {
if (a == null || b == null) {
return Optional.empty();
}
return Optional.of(isMatch(a, b));
}
A primera vista, parece que no es mejor que devolver null
pero los opcionales son de hecho muy superiores .
Tengo un método que busca nulos. ¿Hay alguna manera de reducir el número de líneas en el método? Actualmente, el código se ve "sucio":
private int similarityCount (String one, String two) {
if (one == null && two == null) {
return 1;
} else if (one == null && two != null) {
return 2;
} else if (one != null && two == null) {
return 3;
} else {
if(isMatch(one, two))
return 4;
return 5;
}
}
Deshacerse de las declaraciones IF es muy divertido. Usar un Mapa es una forma de hacer esto. No se ajusta a este caso exactamente debido a la llamada a isMatch, pero lo ofrezco como una alternativa que corta el cuerpo del método similarCount a una sola línea con un IF
El siguiente código tiene dos IF. Si GetOrDefault no evaluó el segundo argumento, podría reducirse a uno. Lamentablemente lo hace el cheque nulo dentro de isMatch es necesario.
Podrías ir mucho más lejos con esto si quisieras. Por ejemplo, isMatch podría devolver 4 o 5 en lugar de un booleano, lo que lo ayudaría a simplificar aún más.
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import java.util.Map;
public class SimilarityCount {
private Map<SimilarityCountKey, Integer> rtn = ImmutableMap.of(new SimilarityCountKey(null, null), 1, new SimilarityCountKey(null, ""), 2, new SimilarityCountKey("", null), 3);
public int similarityCount(String one, String two) {
return rtn.getOrDefault(new SimilarityCountKey(one, two), isMatch(one, two) ? 4 : 5);
}
private boolean isMatch(String one, String two) {
if (one == null || two == null) {
return false;
}
return one.equals(two);
}
private class SimilarityCountKey {
private final boolean one;
private final boolean two;
public SimilarityCountKey(String one, String two) {
this.one = one == null;
this.two = two == null;
}
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
}
}
En caso de que alguien más tenga problemas con otra solución, aquí hay algunas pruebas para ayudarlo a comenzar
import org.junit.Assert;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
public class SimilarityCountTest {
@Test
public void one(){
Assert.assertThat(new SimilarityCount().similarityCount(null,null), is(1));
}
@Test
public void two(){
Assert.assertThat(new SimilarityCount().similarityCount(null,""), is(2));
}
@Test
public void three(){
Assert.assertThat(new SimilarityCount().similarityCount("",null), is(3));
}
@Test
public void four(){
Assert.assertThat(new SimilarityCount().similarityCount("",""), is(4));
}
@Test
public void five(){
Assert.assertThat(new SimilarityCount().similarityCount("a","b"), is(5));
}
}
El código parece lo suficientemente claro para mí. Puede acortarlo con operadores anidados y ternarios:
if(one==null) {
return two==null ? 1 : 2;
}
if(two==null) {
return 3;
}
return isMatch(one,two) ? 4 : 5;
Esto debería ser un poco más rápido si ninguno es nulo, ya que solo realiza una declaración ''si'' en este caso.
private int similarityCount (String one, String two) {
if (one == null || two == null) { // Something is null
if (two != null) { // Only one is null
return 2;
}
if (one != null) { // Only two is null
return 3;
}
return 1; // Both must be null
}
return isMatch(one, two) ? 4 : 5;
}
LOL ... La programación no es un concurso de belleza. Tus códigos
if (one == null && two == null) {
return 1;
} else if (one == null && two != null) {
return 2;
} else if (one != null && two == null) {
return 3;
} else {
if(isMatch(one, two))
return 4;
return 5;
}
NO son sucios, pero son lo suficientemente hermosos para los profanos y también para los expertos. ¿Qué piensas sobre la siguiente codificación
return one == null && two == null ? 1:
one == null && two != null ? 2:
one != null && two == null ? 3:
isMatch(one, two) ? 4 : 5;
Genial, ¿verdad? Bueno, para los profanos es "vudú", para los "expertos" ... uno no debería discutir sobre "gusto", "política" y "religión". PERO desde la perspectiva del rendimiento es así:
- la primera versión es más rápida
- la segunda versión es más torpe (o más lenta)
¿POR QUÉ? Simplemente compile "javac -g: none Test5 * .java" y compare los bytecodes generados. Lo hice y aquí están los resultados:
Primera versión:
public class Test5 {
public static void main(String[] args) {
String one = "1";
String two = "2";
System.out.println(check(one, two));
}
private static int check(String one, String two) {
if (one == null && two == null) {
return 1;
} else if (one == null && two != null) {
return 2;
} else if (one != null && two == null) {
return 3;
} else {
if(isMatch(one, two))
return 4;
return 5;
}
}
public static boolean isMatch(String a, String b) {
return true;
}
}
producido 570 bytes
Segunda versión:
public class Test5a {
public static void main(String[] args) {
String one = "1";
String two = "2";
System.out.println(check(one, two));
}
private static int check(String one, String two) {
return one == null && two == null ? 1:
one == null && two != null ? 2:
one != null && two == null ? 3:
isMatch(one, two) ? 4 : 5;
}
public static boolean isMatch(String a, String b) {
return true;
}
}
produce 581 bytes
Está claro que se deben procesar 11 bytes y eso lleva tiempo ... Cuantos más códigos "excesivos" tenga una aplicación, peor será el rendimiento.
Me gustan las expresiones
private static int similarityCount (String one, String two) {
return one == null ?
similarityCountByTwoOnly(two) :
two == null ? 3 : (isMatch(one, two) ? 4 : 5)
;
}
private static int similarityCountByTwoOnly(String two) {
return two == null ? 1 : 2;
}
Por otro lado, probablemente cuestionaré por qué estás haciendo esto. Asumiría que harías algún tipo de control sobre el entero devuelto después de haberlo evaluado y ramificar tu lógica en función de él. Si ese es el caso, acaba de hacer un chequeo menos legible para null donde el usuario de su método necesita entender el contrato implícito en el valor del entero.
Además, aquí hay una solución simple para cuando necesitas verificar si las cadenas son iguales cuando pueden ser nulas:
boolean same = one == null ? two == null : one.equals(two);
Prefiero condiciones anidadas en tales casos:
private int similarityCount (String one, String two) {
if (one==null) {
if (two==null) {
return 1;
} else {
return 2;
}
} else {
if (two==null) {
return 3;
} else {
return isMatch(one, two) ? 4 : 5;
}
}
}
Por supuesto, puede lograr una versión más corta mediante el uso de más operadores condicionales ternarios.
private int similarityCount (String one, String two) {
if (one==null) {
return (two==null) ? 1 : 2;
} else {
return (two==null) ? 3 : isMatch(one, two) ? 4 : 5;
}
}
O incluso (ahora esto es cada vez menos legible):
private int similarityCount (String one, String two) {
return (one==null) ? ((two==null) ? 1 : 2) : ((two==null) ? 3 : isMatch(one, two) ? 4 : 5);
}
Puede crear una pseudo-lookup-table. Algunas personas fruncen el ceño ante los operadores ternarios anidados y es altamente dependiente del espacio en blanco para la legibilidad, pero puede ser un enfoque muy legible para el retorno condicional:
private int similarityCount (String one, String two) {
return (one == null && two == null) ? 1
: (one == null && two != null) ? 2
: (one != null && two == null) ? 3
: isMatch(one, two) ? 4
: 5;
}
Se puede hacer en una línea usando el operador condicional de Java:
return (one==null?(two==null?1:2):(two==null?3:(isMatch(one,two)?4:5)));
private int similarityCount (String one, String two) {
if (one == null && two == null) {
return 1;
}
if (one == null) {
return 2;
}
if (two == null) {
return 3;
}
if (isMatch(one, two)) {
return 4;
}
return 5;
}