CPF/CPF/HybridDictionary.cs
2023-11-21 23:05:03 +08:00

395 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace CPF
{
/// <summary>
/// 自动切换List 和 Dictionary如果4条记录以下的比直接使用Dictionary稍微省一丢丢内存
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
public class HybridDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private const int CutoverPoint = 4;
List<KeyValue<TKey, TValue>> list;
Dictionary<TKey, TValue> dic;
public TValue this[TKey key]
{
get
{
if (dic != null)
{
return dic[key];
}
else if (list != null)
{
//foreach (var item in list)
//{
// if (item.Key.Equals(key))
// {
// return item.Value;
// }
//}
for (int i = 0; i < list.Count; i++)
{
var item = list[i];
if (item.Key.Equals(key))
{
return item.Value;
//return true;
}
}
}
throw new ArgumentNullException("没有元素");
}
set
{
throw new NotImplementedException();
}
}
ICollection<TKey> IDictionary<TKey, TValue>.Keys
{
get
{
if (dic != null)
{
return dic.Keys;
}
//return list.Select(a => a.Key);
throw new NotImplementedException();
}
}
ICollection<TValue> IDictionary<TKey, TValue>.Values
{
get
{
if (dic != null)
{
return dic.Values;
}
throw new NotImplementedException();
}
}
public int Count
{
get
{
if (dic != null)
{
return dic.Count;
}
else if (list != null)
{
return list.Count;
}
return 0;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
private void ChangeOver()
{
dic = new Dictionary<TKey, TValue>();
foreach (var item in list)
{
dic.Add(item.Key, item.Value);
}
list = null;
}
public void Add(TKey key, TValue value)
{
//Add(new KeyValuePair<TKey, TValue>(key, value));
if (dic != null)
{
dic.Add(key, value);
}
else
{
if (list == null)
{
list = new List<KeyValue<TKey, TValue>>();
list.Add(new KeyValue<TKey, TValue>(key, value));
}
else
{
if (list.Count + 1 >= CutoverPoint)
{
ChangeOver();
dic.Add(key, value);
}
else
{
list.Add(new KeyValue<TKey, TValue>(key, value));
}
}
}
}
public void Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
public void Clear()
{
if (dic != null)
{
dic.Clear();
dic = null;
}
if (list != null)
{
list.Clear();
list = null;
}
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
if (dic != null)
{
return dic.Contains(item);
}
else if (list != null)
{
return list.Contains(new KeyValue<TKey, TValue>(item.Key, item.Value));
}
else
{
return false;
}
}
public bool ContainsKey(TKey key)
{
if (dic != null)
{
return dic.ContainsKey(key);
}
else if (list != null)
{
//return list.Any(a => a.Key.Equals(key));
for (int i = 0; i < list.Count; i++)
{
var item = list[i];
if (item.Key.Equals(key))
{
return true;
}
}
return false;
}
else
{
return false;
}
}
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
//throw new NotImplementedException();
if (dic != null)
{
(dic as ICollection<KeyValuePair<TKey, TValue>>).CopyTo(array, arrayIndex);
}
else
{
//list.CopyTo(array, arrayIndex);
int id = 0;
for (int i = arrayIndex; i < list.Count; i++)
{
var item = list[i];
array[id] = new KeyValuePair<TKey, TValue>(item.Key, item.Value);
id++;
}
}
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
if (dic != null)
{
foreach (var item in dic)
{
yield return item;
}
}
if (list == null)
{
list = new List<KeyValue<TKey, TValue>>();
}
foreach (var item in list)
{
yield return new KeyValuePair<TKey, TValue>(item.Key, item.Value);
}
}
public bool Remove(TKey key)
{
if (dic != null)
{
return dic.Remove(key);
}
else if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
var item = list[i];
if (item.Key.Equals(key))
{
list.RemoveAt(i);
return true;
}
}
//foreach (var item in list)
//{
// if (item.Key.Equals(key))
// {
// list.Remove(item);
// return true;
// }
//}
return false;
}
else
{
if (key == null)
{
throw new ArgumentNullException("key不能为null");
}
return false;
}
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public bool TryGetValue(TKey key, out TValue value)
{
if (dic != null)
{
return dic.TryGetValue(key, out value);
}
if (list != null)
{
//foreach (var item in list)
//{
// if (item.Key.Equals(key))
// {
// value = item.Value;
// return true;
// }
//}
//var length = list.Count;
for (int i = 0; i < list.Count; i++)
{
var item = list[i];
if (item.Key.Equals(key))
{
value = item.Value;
return true;
}
}
}
value = default(TValue);
return false;
}
IEnumerator IEnumerable.GetEnumerator()
{
if (dic != null)
{
foreach (var item in dic)
{
yield return item;
}
}
if (list == null)
{
list = new List<KeyValue<TKey, TValue>>();
}
foreach (var item in list)
{
yield return new KeyValuePair<TKey, TValue>(item.Key, item.Value);
}
//return list.GetEnumerator();
}
}
[Serializable]
struct KeyValue<TKey, TValue>
{
public KeyValue(TKey key, TValue value)
{
this.Key = key;
this.Value = value;
}
public TKey Key;
public TValue Value;
public override bool Equals(object obj)
{
if (obj is KeyValue<TKey, TValue> key)
{
return key.Key.Equal(Key) && key.Value.Equal(Value);
}
return false;
//return base.Equals(obj);
}
public override int GetHashCode()
{
var v = 0;
if (Value != null)
{
v = Value.GetHashCode();
}
var k = 0;
if (Key != null)
{
k = Key.GetHashCode();
}
return v ^ k;
//return base.GetHashCode();
}
public override string ToString()
{
StringBuilder s = new StringBuilder();
s.Append('[');
if (Key != null)
{
s.Append(Key.ToString());
}
s.Append(", ");
if (Value != null)
{
s.Append(Value.ToString());
}
s.Append(']');
return s.ToString();
}
}
}