java.util.LinkedHashMap
我想知道.NET 中是否有对应物?(即,如果我访问一个元素,这些元素会自动(重新)排序。(布尔 accessOrder))。
8 回答
只是为了向读者澄清一点:LinkedHashMap 仅在使用特定的构造函数重载构建时才会如此。通常,元素按插入顺序进行维护。(这对我来说有点奇怪,但没关系。)
我不相信.NET 中有任何这样的类。使用元素的链表和从键到链表节点的字典来构建一个并不难。然后访问将包括获取链表节点,将其移动到头部,并返回值。
如果您愿意,我很乐意在今晚或明天实施它 - 尽管可能没有完整的单元测试等。(全面测试集合是一项耗时的工作!)
一些谷歌搜索似乎表明没有内置的 C# 等效于 LinkedHashMap,但有一些第三方选项可用。
我使用 System.Collections.Specialized.OrderedDictionary 作为 LinkedHashMap 的替代品。它对我有用。OrderedDictionary 有什么我遗漏的吗(是的,它不是通用的,但它适用于 .Net 2 或更高版本)?
Nhibernate 有一个 NHibernate.Util.LinkedHashMap 实现。
如果您的代码中已经有它,就像我一样,它会很方便
我知道这是一个老话题,但是有一个很棒的开源项目可以LinkedHashMap
在 .NET C5中实现
这是LinkedHashMap源代码。
由于 C# 中仍然没有 LinkedHashMap,而我需要这个功能,所以我在最新的 net core (3.1) 上实现了一个。https://github.com/idlerboris/LinkedHashMap/blob/master/CustomCollections/CustomCollections/LinkedHashMap.cs。它包含基本测试,看起来不错,但请随时贡献/报告问题。
游戏已经很晚了,但我在 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);
}
}
由于它基于字典和列表,它至少增加了列表访问和字典访问的时间复杂度。