相当于C#中的LinkedHashSet(Java)

本文关键字:Java LinkedHashSet 中的 相当于 | 更新日期: 2023-09-27 18:25:09

C#中的LinkedHashSet(Java(相当于什么?

相当于C#中的LinkedHashSet(Java)

我完成了未完成的方法,并大致完善了"achitaka-san"发布的类。

public class LinkedHashSet<T> : ISet<T> {
    private readonly IDictionary<T, LinkedListNode<T>> dict;
    private readonly LinkedList<T> list;
    public LinkedHashSet(int initialCapacity) {
        this.dict = new Dictionary<T,LinkedListNode<T>>(initialCapacity);
        this.list = new LinkedList<T>();
    }
    public LinkedHashSet() {
        this.dict = new Dictionary<T,LinkedListNode<T>>();
        this.list = new LinkedList<T>();
    }
    public LinkedHashSet(IEnumerable<T> e) : this() {
        addEnumerable(e);
    }
    public LinkedHashSet(int initialCapacity, IEnumerable<T> e) : this(initialCapacity) {
        addEnumerable(e);
    }
    private void addEnumerable(IEnumerable<T> e) {
        foreach (T t in e) {
            Add(t);
        }
    }
    //
    // ISet implementation
    //
    public bool Add(T item) {
        if (this.dict.ContainsKey(item)) {
            return false;
        }
        LinkedListNode<T> node = this.list.AddLast(item);
        this.dict[item] = node;
        return true;
    }
    public void ExceptWith(IEnumerable<T> other) {
        if (other == null) {
            throw new ArgumentNullException("other cannot be null");
        }
        foreach (T t in other) {
            Remove(t);
        }
    }
    public void IntersectWith(IEnumerable<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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<T> other) {
        if (other == null) {
            throw new ArgumentNullException("other cannot be null");
        }
        T[] ts = new T[Count];
        CopyTo(ts, 0);
        HashSet<T> otherList = new HashSet<T>(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<T> other) {
        if (other == null) {
            throw new ArgumentNullException("other cannot be null");
        }
        foreach (T t in other) {
            Add(t);
        }
    }
    //
    // ICollection<T> implementation
    //
    public int Count {
        get {
            return this.dict.Count;
        }
    }
    public bool IsReadOnly {
        get {
            return this.dict.IsReadOnly;
        }
    }
    void ICollection<T>.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<T> node;
        if (!this.dict.TryGetValue(item, out node)) {
            return false;
        }
        this.dict.Remove(item);
        this.list.Remove(node);
        return true;
    }
    //
    // IEnumerable<T> implementation
    //
    public IEnumerator<T> GetEnumerator() {
        return this.list.GetEnumerator();
    }
    //
    // IEnumerable implementation
    //
    IEnumerator IEnumerable.GetEnumerator() {
        return this.list.GetEnumerator();
    }
}

所需用途:

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

警告:该类在很大程度上未经测试,尤其是 ISet 方法。使用风险自负。
我希望有人觉得这有用。:)

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<String> linkedHashSet = new HashSet<String>(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

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

C# 中没有将链表与 Set 数据结构中所需的唯一性相结合的类,因此,如果需要这两种行为,则需要构建自己的行为。

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

public class OrderedSet<T> : ISet<T>
{
    private readonly IDictionary<T, LinkedListNode<T>> m_Dictionary;
    private readonly LinkedList<T> m_LinkedList;
    public OrderedSet()
    {
        m_Dictionary = new Dictionary<T, LinkedListNode<T>>();
        m_LinkedList = new LinkedList<T>();
    }
    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<T>.Add(T item)
    {
        Add(item);
    }
    public void Clear()
    {
        m_LinkedList.Clear();
        m_Dictionary.Clear();
    }
    public bool Remove(T item)
    {
        LinkedListNode<T> 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<T> 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<T> other)
    {
        throw GetNotSupportedDueToSimplification();
    }
    public void IntersectWith(IEnumerable<T> other)
    {
        throw GetNotSupportedDueToSimplification();
    }
    public void ExceptWith(IEnumerable<T> other)
    {
        throw GetNotSupportedDueToSimplification();
    }
    public bool IsSubsetOf(IEnumerable<T> other)
    {
        throw GetNotSupportedDueToSimplification();
    }
    public void SymmetricExceptWith(IEnumerable<T> other)
    {
        throw GetNotSupportedDueToSimplification();
    }
    public bool IsSupersetOf(IEnumerable<T> other)
    {
        throw GetNotSupportedDueToSimplification();
    }
    public bool IsProperSupersetOf(IEnumerable<T> other)
    {
        throw GetNotSupportedDueToSimplification();
    }
    public bool IsProperSubsetOf(IEnumerable<T> other)
    {
        throw GetNotSupportedDueToSimplification();
    }
    public bool Overlaps(IEnumerable<T> other)
    {
        throw GetNotSupportedDueToSimplification();
    }
    public bool SetEquals(IEnumerable<T> other)
    {
        throw GetNotSupportedDueToSimplification();
    }
    private static Exception GetNotSupportedDueToSimplification()
    {
        return new NotSupportedException("This method is not supported due to simplification of example code.");
    }
}