Давайте цей клас 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
підтримує пошук об’єктів, тому не всі "загальні" мови є такими, як ви описані.