Así que de acuerdo a la API de Java ,Set::contains
Devuelve verdadero si y sólo si este conjunto contiene un elemento tal que e (O == null e == null:? o.equals (e))
Entonces ... ¿por qué es este método devuelve false aunque el conjunto contiene exactamente un elemento que es igual a creds
?
private boolean validate(Credentials creds){
Set<Credentials> acceptedUsers = getAcceptedUsers();
return acceptedUsers.contains(creds);
}
Más específicamente, me inserta algunos printlns
private boolean validate(Credentials creds){
Set<Credentials> acceptedUsers = getAcceptedUsers();
System.out.print("accepted users: ");
System.out.println(acceptedUsers);
System.out.print("accessing user: ");
System.out.println(creds);
System.out.println("items are equal: " + acceptedUsers.stream().map(c -> c.equals(creds)).collect(Collectors.toSet()));
System.out.println("access ok: " + (acceptedUsers.contains(creds) ? "YES" : "NO"));
return acceptedUsers.contains(creds);
}
y esto es lo que tenía que decir:
accepted users: [[
foo
FCDE2B2EDBA56BF408601FB721FE9B5C338D10EE429EA04FAE5511B68FBF8FB9
]]
accessing user: [
foo
FCDE2B2EDBA56BF408601FB721FE9B5C338D10EE429EA04FAE5511B68FBF8FB9
]
items are equal: [true]
access ok: NO
getAcceptedUsers
Actualmente devuelve un conjunto ficticio
private Set<Credentials> getAcceptedUsers(){
return new HashSet<Credentials>(){{add(new Credentials("foo","bar", false));}};
}
y Credentials
se implementa como
class Credentials{
final String username;
final String password;
public Credentials(String username, String password, boolean isPasswordHashed) {
this.username = username;
if(isPasswordHashed) this.password = password;
else {
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
md.update(password.getBytes());
byte[] hash = md.digest();
this.password = (new HexBinaryAdapter()).marshal(hash);
}
}
@Override
public boolean equals(Object obj) {
if(obj == null) return false;
if(!(obj instanceof Credentials)) return false;
Credentials other = (Credentials)obj;
return this.username.equals(other.username) && this.password.equals(other.password);
}
@Override
public String toString() {
return String.format("[\n\t%s\n\t%s\n]", username,password);
}
}
La implementación de equals
método no es suficiente, debe implementar hashCode
también.
Como se puede leer aquí :
Devuelve el valor de código hash para este conjunto. El código hash de un conjunto se define como la suma de los códigos hash de los elementos en el conjunto, donde el código hash de un elemento nula se define a ser cero. Esto asegura que s1.equals (s2) implica que s1.hashCode () == s2.hashCode () para cualquiera de los dos conjuntos S1 y S2, como es requerido por el contrato general de Object.hashCode ().