395 lines
10 KiB
C#
395 lines
10 KiB
C#
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();
|
||
}
|
||
}
|
||
}
|