Vamos ter essa classe C # (seria quase a mesma em Java)
public class MyClass {
public string A {get; set;}
public string B {get; set;}
public override bool Equals(object obj) {
var item = obj as MyClass;
if (item == null || this.A == null || item.A == null)
{
return false;
}
return this.A.equals(item.A);
}
public override int GetHashCode() {
return A != null ? A.GetHashCode() : 0;
}
}
Como você pode ver, a igualdade de duas instâncias de MyClass
depende A
apenas. Portanto, pode haver duas instâncias iguais, mas mantendo informações diferentes em suas B
propriedades.
Em uma biblioteca de coleções padrão de muitas linguagens (incluindo C # e Java, é claro), existe uma Set
( HashSet
em C #), uma coleção que pode conter no máximo um item de cada conjunto de instâncias iguais.
Pode-se adicionar itens, remover itens e verificar se o conjunto contém um item. Mas por que é impossível obter um item específico do conjunto?
HashSet<MyClass> mset = new HashSet<MyClass>();
mset.Add(new MyClass {A = "Hello", B = "Bye"});
//I can do this
if (mset.Contains(new MyClass {A = "Hello", B = "See you"})) {
//something
}
//But I cannot do this, because Get does not exist!!!
MyClass item = mset.Get(new MyClass {A = "Hello", B = "See you"});
Console.WriteLine(item.B); //should print Bye
A única maneira de recuperar meu item é percorrer toda a coleção e verificar a igualdade de todos os itens. No entanto, isso leva O(n)
tempo em vez de O(1)
!
Não encontrei nenhum idioma compatível com o conteúdo de um conjunto até agora. Todas as linguagens "comuns" que conheço (Java, C #, Python, Scala, Haskell ...) parecem ter sido projetadas da mesma maneira: você pode adicionar itens, mas não pode recuperá-los. Existe alguma boa razão para que todos esses idiomas não suportem algo tão fácil e obviamente útil? Eles não podem estar todos errados, certo? Existem idiomas que o suportam? Talvez a recuperação de um item específico de um conjunto esteja errada, mas por quê?
Existem algumas perguntas relacionadas ao SO:
/programming/7283338/getting-an-element-from-a-set
/programming/7760364/how-to-retrieve-actual-item-from-hashsett
Set<E>
implementações são apenas Map<E,Boolean>
internas.
a == b
sempre verdadeira) no caso this.A == null
. O if (item == null || this.A == null || item.A == null)
teste é "exagerado" e verifica muito, possivelmente para criar código artificialmente "de alta qualidade". Vejo esse tipo de "verificação excessiva" e excessivamente correta o tempo todo na Revisão de Código.
std::set
oferece suporte à recuperação de objetos, portanto nem todas as linguagens "comuns" são como você descreve.