Tengamos esta clase de C # (sería casi lo mismo en 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 puede ver, la igualdad de dos instancias MyClass
depende A
solo. Por lo tanto, puede haber dos instancias que sean iguales, pero que contengan información diferente en su B
propiedad.
En una biblioteca de colección estándar de muchos lenguajes (incluidos C # y Java, por supuesto) hay un Set
( HashSet
en C #), que es una colección, que puede contener como máximo un elemento de cada conjunto de instancias iguales.
Se pueden agregar elementos, eliminar elementos y verificar si el conjunto contiene un elemento. Pero, ¿por qué es imposible obtener un artículo en particular del 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
La única forma de recuperar mi artículo es iterar sobre toda la colección y verificar la igualdad de todos los artículos. Sin embargo, esto lleva O(n)
tiempo en lugar de O(1)
!
No he encontrado ningún lenguaje que admita obtener de un conjunto hasta ahora. Todos los lenguajes "comunes" que conozco (Java, C #, Python, Scala, Haskell ...) parecen estar diseñados de la misma manera: puede agregar elementos, pero no puede recuperarlos. ¿Hay alguna buena razón por la cual todos estos idiomas no admiten algo tan fácil y obviamente útil? No pueden estar completamente equivocados, ¿verdad? ¿Hay algún idioma que lo soporte? Tal vez recuperar un elemento particular de un conjunto está mal, pero ¿por qué?
Hay algunas preguntas SO relacionadas:
/programming/7283338/getting-an-element-from-a-set
/programming/7760364/how-to-retrieve-actual-item-from-hashsett
Set<E>
implementaciones son solo Map<E,Boolean>
por dentro.
a == b
siempre cierto) en el caso this.A == null
. La if (item == null || this.A == null || item.A == null)
prueba está "exagerada" y comprueba demasiado, posiblemente para crear código artificialmente de "alta calidad". Veo este tipo de "sobrecomprobación" y ser excesivamente correcto todo el tiempo en la Revisión de Código.
std::set
admite la recuperación de objetos, por lo que no todos los lenguajes "comunes" son como usted describe.