.NET 中的 LinkedHashMap

发布于 2024-07-13 00:44:31 字数 100 浏览 5 评论 0原文

我想知道.NET 中是否有 java.util.LinkedHashMap 的对应项? (即,如果我访问元素,元素会自动(重新)排序。 (boolean accessOrder) )。

I wonder if there is a counterpart to java.util.LinkedHashMap in .NET? (ie. the elements are (re)ordered automatically if I access an element. (boolean accessOrder) ).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

多彩岁月 2024-07-20 00:44:31

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

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

如果您愿意的话,我很乐意今晚或明天实现它 - 尽管可能不会进行完整的单元测试等。(完全测试集合是一项耗时的工作!)

Just to clarify a bit for readers: LinkedHashMap only behaves that way when built with one particular constructor overload. Normally the elements are maintained in insert order. (This feels a little odd to me, but never mind.)

I don't believe there's any such class in .NET. It wouldn't be too hard to build one, using a linked list of elements and a dictionary from key to linked list node. Access would then consist of fetching the linked list node, moving it to the head, and returning the value.

I'd be happy to implement it tonight or tomorrow if you want - although probably not with full unit tests etc. (Fully testing a collection is a time-consuming business!)

怕倦 2024-07-20 00:44:31

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

A bit of Googling seems to show that there is no built in C# equivalent for LinkedHashMap, but there are some third party options available.

唐婉 2024-07-20 00:44:31

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

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

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

Here's a C# implementation I found on a forum:

It's undocumented, but does have some tests. It is not generic, however. At least it's something I guess.

@Jon: I'd appreciate it too if you could do a quick implementation. I imagined that a Dictionary on top of a LinkedList would be best, but I hear there are garbage collection issues with LinkedList that slows things down.

紙鸢 2024-07-20 00:44:31

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

I used System.Collections.Specialized.OrderedDictionary as a replacement for LinkedHashMap. It worked for me. Is there anything I'm missing about OrderedDictionary (yes, it's not generic, but it is available with .Net 2 or newer)?

只是我以为 2024-07-20 00:44:31

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

这是LinkedHashMap< /a> 源代码。

I know this is an old topic, but there is an awesome open source project to implement LinkedHashMap in .NET C5

Here is LinkedHashMap source code.

美煞众生 2024-07-20 00:44:31

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

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

Nhibernate has a NHibernate.Util.LinkedHashMap implementation.

If you already have it on your code, as I had, it can be handy

夏日落 2024-07-20 00:44:31

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

As there is still no LinkedHashMap in C#, and I needed this functionality, I've implemented one on the latest net core (3.1). https://github.com/idlerboris/LinkedHashMap/blob/master/CustomCollections/CustomCollections/LinkedHashMap.cs. It's covered with basic tests and seems to be good, but feel free to contribute/report issues.

负佳期 2024-07-20 00:44:31

进入这个游戏已经很晚了,但我在 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);

        }

    }

因为它基于 Dictionary 和 List,所以它至少增加了时间复杂度列表访问和字典访问。

pretty late to the game, but I implemented the LinkedHashMap (Java) equivalent in C# as LinkedDictionary as follows:

    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;
            }
        }
    }

And a simple UnitTest where I compare it to 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 => 
quot;{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 => 
quot;{i.Key} :{i.Value}").ToList().ForEach(Console.WriteLine);

        }

    }

As it is based on a Dictionary and a List it at least adds the time complexity of List accesses and Dictionary accesses.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文