Давайте цей клас C # (це було б майже те саме в 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;
}
}
Як бачимо, рівність двох примірників MyClassзалежить Aтільки від. Таким чином, можуть бути два екземпляри, які є рівними, але містять різні відомості у своїй Bвласності.
У стандартній бібліотеці колекцій багатьох мов (включаючи C # і Java, звичайно) є Set( HashSetу C #) - це колекція, яка може вмістити щонайменше один елемент з кожного набору рівних екземплярів.
Можна додавати предмети, видаляти предмети та перевіряти, чи містить набір предмет. Але чому неможливо отримати певний предмет із набору?
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
Єдиний спосіб отримати мій предмет - це повторити повну колекцію та перевірити всі предмети на рівність. Однак на це потрібен O(n)час замість O(1)!
Я досі не знайшов жодної мови, яка підтримує, набір із набору. Усі "загальні" мови, які я знаю (Java, C #, Python, Scala, Haskell ...) здаються створеними однаково: ви можете додавати елементи, але ви не можете їх отримати. Чи є якась вагома причина, чому всі ці мови не підтримують щось таке легке і очевидно корисне? Вони не можуть бути помилковими, правда? Чи є мови, які це підтримують? Можливо, вилучення певного предмета з набору невірно, але чому?
Є декілька пов’язаних питань щодо ТА:
/programming/7283338/getting-an-element-from-a-set
/programming/7760364/how-to-retrieve-actual-item-from-hashsett
Set<E>реалізацій знаходяться лише Map<E,Boolean>зсередини.
a == bзавжди вірно) у випадку this.A == null. if (item == null || this.A == null || item.A == null)Тест «перестаралися» і перевіряє багато, можливо , для того , щоб штучно створити «високої якості» коду. Я бачу таке "перевірка" і весь час надмірно коректуюсь у Code Review.
std::setпідтримує пошук об’єктів, тому не всі "загальні" мови є такими, як ви описані.