HashSet은 요소와 동등성을 어떻게 비교합니까?
나는 수업이 있습니다 IComparable
:
public class a : IComparable
{
public int Id { get; set; }
public string Name { get; set; }
public a(int id)
{
this.Id = id;
}
public int CompareTo(object obj)
{
return this.Id.CompareTo(((a)obj).Id);
}
}
이 클래스의 객체 목록을 해시 세트에 추가하면 :
a a1 = new a(1);
a a2 = new a(2);
HashSet<a> ha = new HashSet<a>();
ha.add(a1);
ha.add(a2);
ha.add(a1);
모든 것이 잘하고 ha.count
있다 2
,하지만 :
a a1 = new a(1);
a a2 = new a(2);
HashSet<a> ha = new HashSet<a>();
ha.add(a1);
ha.add(a2);
ha.add(new a(1));
지금 ha.count
은 3
입니다.
- 의 방법을
HashSet
존중 하지 않는 이유는 무엇입니까?a
CompareTo
- 가
HashSet
고유 한 개체의 목록을 가장 좋은 방법은?
그것은 사용합니다 ( 당신이 건축에 다른 하나를 지정하지 않은 경우).IEqualityComparer<T>
EqualityComparer<T>.Default
세트에 요소를 추가하면 해시 코드를 찾고 IEqualityComparer<T>.GetHashCode
해시 코드와 요소를 모두 저장합니다 (물론 요소가 이미 세트에 있는지 확인한 후).
를 찾으려면 요소 먼저를 사용하여 IEqualityComparer<T>.GetHashCode
해시 코드를 찾은 다음 동일한 해시 코드를 가진 모든 요소에 IEqualityComparer<T>.Equals
대해 실제 평등을 비교 하는 데 사용 합니다.
즉, 두 가지 옵션이 있습니다.
IEqualityComparer<T>
생성자 에 사용자 정의 를 전달하십시오. 옵션은이T
자체를 수정할 수 없거나 기본이 아닌 동등 관계를 원하는 경우에 추론 적합한 옵션입니다 (예 : "부정 사용자 ID를 가진 모든 사용자는 동일하게 간주 됩니다 "). 거의 유형 자체 이것은 에서Foo
구현되지 않으며 (즉, 구현하지 않음IEqualityComparer<Foo>
) 비교 전용으로 사용되는 별도의 유형 입니다 .GetHashCode
및 을 재정 의하여 형식 자체에서 동등성을 구현Equals(object)
합니다. 이상적으로는IEquatable<T>
특히 값 형식 인 경우 형식으로 구현 합니다. 메소드는 기본 동등성 비교기에 의해 호출됩니다.
평등을 비교하면 쉽게 수없는 상황이 있기 때문에 어느 것도 순서 와 관련이 없습니다. 이것은 Dictionary<TKey, TValue>
기본적으로 모두 동일 합니다.
비교 대신 등식 순서 를 사용하는 집합을 원한다면 .NET 4에서 사용해야 합니다 . 이것은 -를 사용 하거나 위임하는 경우 사용 합니다.SortedSet<T>
IComparer<T>
IEqualityComparer<T>
IComparer<T>.Compare
IComparable<T>.CompareTo
IComparable.CompareTo
Comparer<T>.Default
대답하지 않은 채로 대답 진 대답에 대한 설명은 다음과 대답합니다. 객체 유형 HashSet<T>
을 구현할 필요는 IEqualityComparer<T>
없지만 대신 Object.GetHashCode()
과 를 재정의해야 Object.Equals(Object obj)
합니다.
이 대신에 :
public class a : IEqualityComparer<a>
{
public int GetHashCode(a obj) { /* Implementation */ }
public bool Equals(a obj1, a obj2) { /* Implementation */ }
}
당신은 제출합니다 :
public class a
{
public override int GetHashCode() { /* Implementation */ }
public override bool Equals(object obj) { /* Implementation */ }
}
그것은 미묘하지만 이것은 HashSet이 의도 된 방식으로 작동하도록 노력하는 하루 중 더 나은 날을 위해 나를 넘어 뜨 렸습니다. 다른 사람이 말한 것처럼 그리고, HashSet<a>
호출 끝날 a.GetHashCode()
하고 필요 a.Equals(obj)
에 따라 설정 작업을 할 때.
HashSet
사용 Equals
하고 GetHashCode()
.
CompareTo
주문 세트입니다.
고유 한 반복 순서에 신경 쓰지 않는 경우 HashSet<T>
일반적으로 최선의 선택입니다.
생성자 HashSet는 새로운 객체를 추가하기 위해 IEqualityComparer를 구현하는 객체를받습니다. HashSet에서 메소드를 사용하려면 Equals, GetHashCode를 재정의해야합니다.
namespace HashSet
{
public class Employe
{
public Employe() {
}
public string Name { get; set; }
public override string ToString() {
return Name;
}
public override bool Equals(object obj) {
return this.Name.Equals(((Employe)obj).Name);
}
public override int GetHashCode() {
return this.Name.GetHashCode();
}
}
class EmployeComparer : IEqualityComparer<Employe>
{
public bool Equals(Employe x, Employe y)
{
return x.Name.Trim().ToLower().Equals(y.Name.Trim().ToLower());
}
public int GetHashCode(Employe obj)
{
return obj.Name.GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
HashSet<Employe> hashSet = new HashSet<Employe>(new EmployeComparer());
hashSet.Add(new Employe() { Name = "Nik" });
hashSet.Add(new Employe() { Name = "Rob" });
hashSet.Add(new Employe() { Name = "Joe" });
Display(hashSet);
hashSet.Add(new Employe() { Name = "Rob" });
Display(hashSet);
HashSet<Employe> hashSetB = new HashSet<Employe>(new EmployeComparer());
hashSetB.Add(new Employe() { Name = "Max" });
hashSetB.Add(new Employe() { Name = "Solomon" });
hashSetB.Add(new Employe() { Name = "Werter" });
hashSetB.Add(new Employe() { Name = "Rob" });
Display(hashSetB);
var union = hashSet.Union<Employe>(hashSetB).ToList();
Display(union);
var inter = hashSet.Intersect<Employe>(hashSetB).ToList();
Display(inter);
var except = hashSet.Except<Employe>(hashSetB).ToList();
Display(except);
Console.ReadKey();
}
static void Display(HashSet<Employe> hashSet)
{
if (hashSet.Count == 0)
{
Console.Write("Collection is Empty");
return;
}
foreach (var item in hashSet)
{
Console.Write("{0}, ", item);
}
Console.Write("\n");
}
static void Display(List<Employe> list)
{
if (list.Count == 0)
{
Console.WriteLine("Collection is Empty");
return;
}
foreach (var item in list)
{
Console.Write("{0}, ", item);
}
Console.Write("\n");
}
}
}
참고 URL : https://stackoverflow.com/questions/8952003/how-does-hashset-compare-elements-for-equality
'IT' 카테고리의 다른 글
프래그먼트 분리와 제거의 차이점은 무엇입니까? (0) | 2020.07.29 |
---|---|
std :: function 및 std :: bind : 무엇이며 언제 어디에서 가지고 있습니까? (0) | 2020.07.29 |
CSS 배경 이미지 대체 속성 (0) | 2020.07.29 |
.NET 고유 객체 식별자 (0) | 2020.07.29 |
c = ++ (a + b)가 발생 오류를 발생시키는 이유는 무엇입니까? (0) | 2020.07.29 |