25

java.util.LinkedHashMap我想知道.NET 中是否有对应物?(即,如果我访问一个元素,这些元素会自动(重新)排序。(布尔 accessOrder))。

4

8 回答 8

16

只是为了向读者澄清一点:LinkedHashMap 仅在使用特定的构造函数重载构建时才会如此。通常,元素按插入顺序进行维护。(这对我来说有点奇怪,但没关系。)

我不相信.NET 中有任何这样的类。使用元素的链表和从键到链表节点的字典来构建一个并不难。然后访问将包括获取链表节点,将其移动到头部,并返回值。

如果您愿意,我很乐意在今晚或明天实施它 - 尽管可能没有完整的单元测试等。(全面测试集合是一项耗时的工作!)

于 2009-01-28T09:28:00.893 回答
6

一些谷歌搜索似乎表明没有内置的 C# 等效于 LinkedHashMap,但有一些第三方选项可用。

于 2009-01-28T09:27:30.210 回答
2

这是我在论坛上找到的 C# 实现:

它没有记录,但确实有一些测试。然而,它不是通用的。至少这是我猜的。

@Jon:如果您能快速实施,我也将不胜感激。我认为 LinkedList 之上的 Dictionary 会是最好的,但我听说LinkedList 存在垃圾收集问题,这会减慢速度。

于 2009-06-05T15:05:13.917 回答
1

我使用 System.Collections.Specialized.OrderedDictionary 作为 LinkedHashMap 的替代品。它对我有用。OrderedDictionary 有什么我遗漏的吗(是的,它不是通用的,但它适用于 .Net 2 或更高版本)?

于 2014-05-09T19:28:25.673 回答
1

Nhibernate 有一个 NHibernate.Util.LinkedHashMap 实现。

如果您的代码中已经有它,就像我一样,它会很方便

于 2016-04-07T11:27:40.920 回答
1

我知道这是一个老话题,但是有一个很棒的开源项目可以LinkedHashMap在 .NET C5中实现

这是LinkedHashMap源代码。

于 2021-10-25T15:20:43.780 回答
0

由于 C# 中仍然没有 LinkedHashMap,而我需要这个功能,所以我在最新的 net core (3.1) 上实现了一个。https://github.com/idlerboris/LinkedHashMap/blob/master/CustomCollections/CustomCollections/LinkedHashMap.cs。它包含基本测试,看起来不错,但请随时贡献/报告问题。

于 2020-04-21T02:48:02.800 回答
0

游戏已经很晚了,但我在 C# 中将 LinkedHashMap (Java) 等效实现为 LinkedDictionary,如下所示:

    public class LinkedDictionary<K, V> : IDictionary<K, V>, ICollection<KeyValuePair<K, V>>, IEnumerable<KeyValuePair<K, V>>
    {

    private List<K> list = new List<K>();
    private Dictionary<K, V> dictionary = new Dictionary<K, V>();

    public LinkedDictionary()
    {

    }

    public V this[K key] {
        get {
            return this.dictionary[key];
        }
        set {
            this.dictionary[key] = value;
            if (!this.list.Contains(key))
            {
                this.list.Add(key);
            }
        }
    }
            
    public int Count => this.dictionary.Count;

    public bool IsReadOnly => false;

    ICollection<K> IDictionary<K, V>.Keys => this.list;

    ICollection<V> IDictionary<K, V>.Values
    {
        get
        {
            List<V> values = new List<V>(this.dictionary.Count);
            foreach(K key in this.list)
            {
                V value = default(V);
                this.dictionary.TryGetValue(key, out value);
                values.Add(value);
            }
            return values;
        }
    }

    public void Add(KeyValuePair<K, V> item)
    {
        this.dictionary.Add(item.Key, item.Value);
        if (!this.list.Contains(item.Key))
        {
            this.list.Add(item.Key);
        }
    }

    public void Add(K key, V value)
    {
        this.dictionary.Add(key, value);
        if (!this.list.Contains(key))
        {
            this.list.Add(key);
        }
    }

    public void Clear()
    {
        this.dictionary.Clear();
        this.list.Clear();
    }

    public bool Contains(KeyValuePair<K, V> item)
    {
        return this.dictionary.Contains(item);
    }

    public bool ContainsKey(K key)
    {
        return this.dictionary.ContainsKey(key);
    }

    public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex)
    {
        throw new NotImplementedException();
    }

    public bool Remove(KeyValuePair<K, V> item)
    {
        if (this.Contains(item)){
            this.list.Remove(item.Key);
            return this.dictionary.Remove(item.Key);
        } else
        {
            return false;
        }
    }

    public bool Remove(K key)
    {
        if (this.dictionary.ContainsKey(key))
        {
            this.list.Remove(key);
            return this.dictionary.Remove(key);
        }
        else
        {
            return false;
        }
    }

     public bool TryGetValue(K key, [MaybeNullWhen(false)] out V value)
    {
        return this.dictionary.TryGetValue(key, out value);
    }

    public V Get(K key)
    {
        V value = default(V);
        this.dictionary.TryGetValue(key, out value);
        return value;
    }

    public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
    {
        foreach (K key in this.list){
            V value = default(V);
            this.dictionary.TryGetValue(key, out value);
            yield return new KeyValuePair<K, V>(key, value);
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    private class LinkedDictionaryIterator<K, V> : IEnumerator<V>
    {

        private int i;
        private readonly Dictionary<K, V> dictionary;
        private readonly List<K> list;
        
        public LinkedDictionaryIterator(Dictionary<K, V> dictionary, List<K> list)
        {
            this.dictionary = dictionary;
            this.list = list;
            this.i = 0;
        }

        public void Dispose()
        {
            
        }

        public bool MoveNext()
        {
            return this.i < this.dictionary.Count;
        }

        public void Reset()
        {
            this.i = 0;
        }

        public KeyValuePair<K, V> Current
        {
            get
            {
                int ii = this.i;
                ++this.i;
                V value = default(V);
                K key = this.list[ii];
                this.dictionary.TryGetValue(key, out value);
                return new KeyValuePair<K, V>(key, value);
            }
        }

        V IEnumerator<V>.Current
        {
            get
            {
                int ii = this.i;
                ++this.i;
                V value = default(V);
                K key = this.list[ii];
                this.dictionary.TryGetValue(key, out value);
                return value;
            }
        }

        object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }
    }

还有一个简单的 UnitTest,我将它与 Dictionary 进行比较

    class UnitTest_LinkedDictionary
    {
        [Test]
        public void Test00()
        {
            LinkedDictionary<string, int> d = new LinkedDictionary<string, int>();



            d.Add("1", 1);
            d.Add("2", 2);
            d.Add("3", 3);
            d.Remove("2");
            d.Add("4", 4);

            d.Select(i => $"{i.Key}: {i.Value}").ToList().ForEach(Console.WriteLine);

        }

        [Test]
        public void Test01()
        {
            Dictionary<string, int> d = new Dictionary<string, int>();

            d.Add("1", 1);
            d.Add("2", 2);
            d.Add("3", 3);
            d.Remove("2");
            d.Add("4", 4);

            d.Select(i => $"{i.Key} :{i.Value}").ToList().ForEach(Console.WriteLine);

        }

    }

由于它基于字典和列表,它至少增加了列表访问和字典访问的时间复杂度。

于 2022-02-22T22:44:18.680 回答