C#中LinkedHashSet(Java)的等价物是什么?

C#中LinkedHashSet(Java)的等价物是什么?

我完成了未完成的方法,并且普遍打磨了“achitaka-san”发布的课程。

public class LinkedHashSet : ISet { private readonly IDictionary> dict; private readonly LinkedList list; public LinkedHashSet(int initialCapacity) { this.dict = new Dictionary>(initialCapacity); this.list = new LinkedList(); } public LinkedHashSet() { this.dict = new Dictionary>(); this.list = new LinkedList(); } public LinkedHashSet(IEnumerable e) : this() { addEnumerable(e); } public LinkedHashSet(int initialCapacity, IEnumerable e) : this(initialCapacity) { addEnumerable(e); } private void addEnumerable(IEnumerable e) { foreach (T t in e) { Add(t); } } // // ISet implementation // public bool Add(T item) { if (this.dict.ContainsKey(item)) { return false; } LinkedListNode node = this.list.AddLast(item); this.dict[item] = node; return true; } public void ExceptWith(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other cannot be null"); } foreach (T t in other) { Remove(t); } } public void IntersectWith(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other cannot be null"); } T[] ts = new T[Count]; CopyTo(ts, 0); foreach (T t in ts) { if (!System.Linq.Enumerable.Contains(other, t)) { Remove(t); } } } public bool IsProperSubsetOf(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other cannot be null"); } int contains = 0; int noContains = 0; foreach (T t in other) { if (Contains(t)) { contains++; } else { noContains++; } } return contains == Count && noContains > 0; } public bool IsProperSupersetOf(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other cannot be null"); } int otherCount = System.Linq.Enumerable.Count(other); if (Count <= otherCount) { return false; } int contains = 0; int noContains = 0; foreach (T t in this) { if (System.Linq.Enumerable.Contains(other, t)) { contains++; } else { noContains++; } } return contains == otherCount && noContains > 0; } public bool IsSubsetOf(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other cannot be null"); } foreach (T t in this) { if (!System.Linq.Enumerable.Contains(other, t)) { return false; } } return true; } public bool IsSupersetOf(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other cannot be null"); } foreach (T t in other) { if (!Contains(t)) { return false; } } return true; } public bool Overlaps(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other cannot be null"); } foreach (T t in other) { if (Contains(t)) { return true; } } return false; } public bool SetEquals(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other cannot be null"); } int otherCount = System.Linq.Enumerable.Count(other); if (Count != otherCount) { return false; } return IsSupersetOf(other); } public void SymmetricExceptWith(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other cannot be null"); } T[] ts = new T[Count]; CopyTo(ts, 0); HashSet otherList = new HashSet(other); foreach (T t in ts) { if (otherList.Contains(t)) { Remove(t); otherList.Remove(t); } } foreach (T t in otherList) { Add(t); } } public void UnionWith(IEnumerable other) { if (other == null) { throw new ArgumentNullException("other cannot be null"); } foreach (T t in other) { Add(t); } } // // ICollection implementation // public int Count { get { return this.dict.Count; } } public bool IsReadOnly { get { return this.dict.IsReadOnly; } } void ICollection.Add(T item) { Add(item); } public void Clear() { this.dict.Clear(); this.list.Clear(); } public bool Contains(T item) { return this.dict.ContainsKey(item); } public void CopyTo(T[] array, int arrayIndex) { this.list.CopyTo(array, arrayIndex); } public bool Remove(T item) { LinkedListNode node; if (!this.dict.TryGetValue(item, out node)) { return false; } this.dict.Remove(item); this.list.Remove(node); return true; } // // IEnumerable implementation // public IEnumerator GetEnumerator() { return this.list.GetEnumerator(); } // // IEnumerable implementation // IEnumerator IEnumerable.GetEnumerator() { return this.list.GetEnumerator(); } } 

要求使用:

 using System; using System.Collections; using System.Collections.Generic; 

警告:该类很大程度上未经测试,尤其是ISet方法。 使用风险由您自己承担。
我希望有人觉得这很有用。 🙂

C#中没有直接的等价物。 要使用的适当类取决于所需的行为。 HashSet类将保留元素的唯一性。 您可能还想查看SortedSetSortedDictionary

C#中没有类将链接列表与Set数据结构中所需的唯一性组合在一起,因此如果您需要这两种行为,那么您将需要构建自己的行为。

我简要地实现了一个保证插入顺序的HashSet 。 它使用Dictionary查找项目,使用LinkedList保存顺序。 所有三个插入,删除和查找工作仍在O(1)中。

 public class OrderedSet : ISet { private readonly IDictionary> m_Dictionary; private readonly LinkedList m_LinkedList; public OrderedSet() { m_Dictionary = new Dictionary>(); m_LinkedList = new LinkedList(); } public bool Add(T item) { if (m_Dictionary.ContainsKey(item)) return false; var node = m_LinkedList.AddLast(item); m_Dictionary.Add(item, node); return true; } void ICollection.Add(T item) { Add(item); } public void Clear() { m_LinkedList.Clear(); m_Dictionary.Clear(); } public bool Remove(T item) { LinkedListNode node; bool found = m_Dictionary.TryGetValue(item, out node); if (!found) return false; m_Dictionary.Remove(item); m_LinkedList.Remove(node); return true; } public int Count { get { return m_Dictionary.Count; } } public IEnumerator GetEnumerator() { return m_LinkedList.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public bool Contains(T item) { return m_Dictionary.ContainsKey(item); } public void CopyTo(T[] array, int arrayIndex) { m_LinkedList.CopyTo(array, arrayIndex); } public virtual bool IsReadOnly { get { return m_Dictionary.IsReadOnly; } } public void UnionWith(IEnumerable other) { throw GetNotSupportedDueToSimplification(); } public void IntersectWith(IEnumerable other) { throw GetNotSupportedDueToSimplification(); } public void ExceptWith(IEnumerable other) { throw GetNotSupportedDueToSimplification(); } public bool IsSubsetOf(IEnumerable other) { throw GetNotSupportedDueToSimplification(); } public void SymmetricExceptWith(IEnumerable other) { throw GetNotSupportedDueToSimplification(); } public bool IsSupersetOf(IEnumerable other) { throw GetNotSupportedDueToSimplification(); } public bool IsProperSupersetOf(IEnumerable other) { throw GetNotSupportedDueToSimplification(); } public bool IsProperSubsetOf(IEnumerable other) { throw GetNotSupportedDueToSimplification(); } public bool Overlaps(IEnumerable other) { throw GetNotSupportedDueToSimplification(); } public bool SetEquals(IEnumerable other) { throw GetNotSupportedDueToSimplification(); } private static Exception GetNotSupportedDueToSimplification() { return new NotSupportedException("This method is not supported due to simplification of example code."); } } 

HashSet完成这项工作,因为它几乎等同于Java中的LinkedHashSet。 HashSet由链表支持 – 尽管文档没有明确声明它保留了订单,或者它是由基于数组的链表支持的。 您可以从源代码中看到实现是LinkedHashSet。

不像Java LinkedHashSet那样允许重复。 这个和LinkedHashSet之间的一个区别是,如果从集合中删除某些东西,它只会在元素中将元素标记为空闲,因此在remove()之后添加一个项目会在“追加”之前填充空数组插槽。 解决这个问题的方法是调用TrimExcess()方法。 因此,虽然它在许多用例中并不完全相同,例如序列化和反序列化,并且对于有效的不可变集,一旦创建它就可以很好地工作。

您始终可以子类化并覆盖remove()以始终调用TrimExcess()以获得相同的行为。 为清晰起见,您可以将类命名为LinkedHashSet!

 using System; using System.Collections.Generic; namespace ConsoleApplication { public class Program { public static void Main(string[] args) { String[] crew = {"Spock", "Kirk", "Bones", "Picard", "Uhura", "Chekov"}; HashSet linkedHashSet = new HashSet(crew); // Show order is preserved foreach(String value in linkedHashSet){ Console.Write(value); Console.Write(" "); } // Remove from the middle linkedHashSet.Remove("Picard"); Console.WriteLine(); foreach(String value in linkedHashSet){ Console.Write(value); Console.Write(" "); } // Add it back but it is back in the middle not the end linkedHashSet.Add("Picard"); Console.WriteLine(); foreach(String value in linkedHashSet){ Console.Write(value); Console.Write(" "); } // Remove and trim then add linkedHashSet.Remove("Picard"); linkedHashSet.TrimExcess(); linkedHashSet.Add("Picard"); Console.WriteLine(); foreach(String value in linkedHashSet){ Console.Write(value); Console.Write(" "); } Console.WriteLine(); } } } 

输出:

 Spock Kirk Bones Picard Uhura Chekov Spock Kirk Bones Uhura Chekov Spock Kirk Bones Picard Uhura Chekov Spock Kirk Bones Uhura Chekov Picard