Lucene.Net  3.0.3
Lucene.Net is a .NET port of the Java Lucene Indexing Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties
HashMap.cs
Go to the documentation of this file.
1 /*
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements. See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership. The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License. You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied. See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20 */
21 
22 using System;
23 using System.Collections;
24 using System.Collections.Generic;
25 
26 namespace Lucene.Net.Support
27 {
55  [Serializable]
56  public class HashMap<TKey, TValue> : IDictionary<TKey, TValue>
57  {
58  internal IEqualityComparer<TKey> _comparer;
59  internal Dictionary<TKey, TValue> _dict;
60 
61  // Indicates if a null key has been assigned, used for iteration
62  private bool _hasNullValue;
63  // stores the value for the null key
64  private TValue _nullValue;
65  // Indicates the type of key is a non-nullable valuetype
66  private bool _isValueType;
67 
68  public HashMap()
69  : this(0)
70  { }
71 
72  public HashMap(IEqualityComparer<TKey> comparer)
73  : this(0, comparer)
74  {
75 
76  }
77 
78  public HashMap(int initialCapacity)
79  : this(initialCapacity, EqualityComparer<TKey>.Default)
80  {
81 
82  }
83 
84  public HashMap(int initialCapacity, IEqualityComparer<TKey> comparer)
85  {
86  _comparer = comparer;
87  _dict = new Dictionary<TKey, TValue>(initialCapacity, _comparer);
88  _hasNullValue = false;
89 
90  if (typeof(TKey).IsValueType)
91  {
92  _isValueType = Nullable.GetUnderlyingType(typeof(TKey)) == null;
93  }
94  }
95 
96  public HashMap(IEnumerable<KeyValuePair<TKey, TValue>> other)
97  : this(0)
98  {
99  foreach (var kvp in other)
100  {
101  Add(kvp.Key, kvp.Value);
102  }
103  }
104 
105  public bool ContainsValue(TValue value)
106  {
107  if (!_isValueType && _hasNullValue && _nullValue.Equals(value))
108  return true;
109 
110  return _dict.ContainsValue(value);
111  }
112 
113  #region Implementation of IEnumerable
114 
115  public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
116  {
117  if (!_isValueType && _hasNullValue)
118  {
119  yield return new KeyValuePair<TKey, TValue>(default(TKey), _nullValue);
120  }
121  foreach (var kvp in _dict)
122  {
123  yield return kvp;
124  }
125  }
126 
127  IEnumerator IEnumerable.GetEnumerator()
128  {
129  return GetEnumerator();
130  }
131 
132  #endregion
133 
134  #region Implementation of ICollection<KeyValuePair<TKey,TValue>>
135 
136  void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
137  {
138  Add(item.Key, item.Value);
139  }
140 
141  public void Clear()
142  {
143  _hasNullValue = false;
144  _nullValue = default(TValue);
145  _dict.Clear();
146  }
147 
148  bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
149  {
150  if (!_isValueType && _comparer.Equals(item.Key, default(TKey)))
151  {
152  return _hasNullValue && EqualityComparer<TValue>.Default.Equals(item.Value, _nullValue);
153  }
154 
155  return ((ICollection<KeyValuePair<TKey, TValue>>)_dict).Contains(item);
156  }
157 
158  void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
159  {
160  ((ICollection<KeyValuePair<TKey, TValue>>) _dict).CopyTo(array, arrayIndex);
161  if(!_isValueType && _hasNullValue)
162  {
163  array[array.Length - 1] = new KeyValuePair<TKey, TValue>(default(TKey), _nullValue);
164  }
165  }
166 
167  public bool Remove(KeyValuePair<TKey, TValue> item)
168  {
169  if (!_isValueType && _comparer.Equals(item.Key, default(TKey)))
170  {
171  if (!_hasNullValue)
172  return false;
173 
174  _hasNullValue = false;
175  _nullValue = default(TValue);
176  return true;
177  }
178 
179  return ((ICollection<KeyValuePair<TKey, TValue>>)_dict).Remove(item);
180  }
181 
182  public int Count
183  {
184  get { return _dict.Count + (_hasNullValue ? 1 : 0); }
185  }
186 
187  public bool IsReadOnly
188  {
189  get { return false; }
190  }
191 
192  #endregion
193 
194  #region Implementation of IDictionary<TKey,TValue>
195 
196  public bool ContainsKey(TKey key)
197  {
198  if (!_isValueType && _comparer.Equals(key, default(TKey)))
199  {
200  if (_hasNullValue)
201  {
202  return true;
203  }
204  return false;
205  }
206 
207  return _dict.ContainsKey(key);
208  }
209 
210  public virtual void Add(TKey key, TValue value)
211  {
212  if (!_isValueType && _comparer.Equals(key, default(TKey)))
213  {
214  _hasNullValue = true;
215  _nullValue = value;
216  }
217  else
218  {
219  _dict[key] = value;
220  }
221  }
222 
223  public bool Remove(TKey key)
224  {
225  if (!_isValueType && _comparer.Equals(key, default(TKey)))
226  {
227  _hasNullValue = false;
228  _nullValue = default(TValue);
229  return true;
230  }
231  else
232  {
233  return _dict.Remove(key);
234  }
235  }
236 
237  public bool TryGetValue(TKey key, out TValue value)
238  {
239  if (!_isValueType && _comparer.Equals(key, default(TKey)))
240  {
241  if (_hasNullValue)
242  {
243  value = _nullValue;
244  return true;
245  }
246 
247  value = default(TValue);
248  return false;
249  }
250  else
251  {
252  return _dict.TryGetValue(key, out value);
253  }
254  }
255 
256  public TValue this[TKey key]
257  {
258  get
259  {
260  if (!_isValueType && _comparer.Equals(key, default(TKey)))
261  {
262  if (!_hasNullValue)
263  {
264  return default(TValue);
265  }
266  return _nullValue;
267  }
268  return _dict.ContainsKey(key) ? _dict[key] : default(TValue);
269  }
270  set { Add(key, value); }
271  }
272 
273  public ICollection<TKey> Keys
274  {
275  get
276  {
277  if (!_hasNullValue) return _dict.Keys;
278 
279  // Using a List<T> to generate an ICollection<TKey>
280  // would incur a costly copy of the dict's KeyCollection
281  // use out own wrapper instead
282  return new NullKeyCollection(_dict);
283  }
284  }
285 
286  public ICollection<TValue> Values
287  {
288  get
289  {
290  if (!_hasNullValue) return _dict.Values;
291 
292  // Using a List<T> to generate an ICollection<TValue>
293  // would incur a costly copy of the dict's ValueCollection
294  // use out own wrapper instead
295  return new NullValueCollection(_dict, _nullValue);
296  }
297  }
298 
299  #endregion
300 
301  #region NullValueCollection
302 
307  class NullValueCollection : ICollection<TValue>
308  {
309  private readonly TValue _nullValue;
310  private readonly Dictionary<TKey, TValue> _internalDict;
311 
312  public NullValueCollection(Dictionary<TKey, TValue> dict, TValue nullValue)
313  {
314  _internalDict = dict;
315  _nullValue = nullValue;
316  }
317 
318  #region Implementation of IEnumerable
319 
320  public IEnumerator<TValue> GetEnumerator()
321  {
322  yield return _nullValue;
323 
324  foreach (var val in _internalDict.Values)
325  {
326  yield return val;
327  }
328  }
329 
330  IEnumerator IEnumerable.GetEnumerator()
331  {
332  return GetEnumerator();
333  }
334 
335  #endregion
336 
337  #region Implementation of ICollection<TValue>
338 
339  public void CopyTo(TValue[] array, int arrayIndex)
340  {
341  throw new NotImplementedException("Implement as needed");
342  }
343 
344  public int Count
345  {
346  get { return _internalDict.Count + 1; }
347  }
348 
349  public bool IsReadOnly
350  {
351  get { return true; }
352  }
353 
354  #region Explicit Interface Methods
355 
356  void ICollection<TValue>.Add(TValue item)
357  {
358  throw new NotSupportedException();
359  }
360 
361  void ICollection<TValue>.Clear()
362  {
363  throw new NotSupportedException();
364  }
365 
366  bool ICollection<TValue>.Contains(TValue item)
367  {
368  throw new NotSupportedException();
369  }
370 
371  bool ICollection<TValue>.Remove(TValue item)
372  {
373  throw new NotSupportedException("Collection is read only!");
374  }
375  #endregion
376 
377  #endregion
378  }
379 
380  #endregion
381 
382  #region NullKeyCollection
383 
384 
385 
386 
387  class NullKeyCollection : ICollection<TKey>
388  {
389  private readonly Dictionary<TKey, TValue> _internalDict;
390 
391  public NullKeyCollection(Dictionary<TKey, TValue> dict)
392  {
393  _internalDict = dict;
394  }
395 
396  public IEnumerator<TKey> GetEnumerator()
397  {
398  yield return default(TKey);
399  foreach (var key in _internalDict.Keys)
400  {
401  yield return key;
402  }
403  }
404 
405  IEnumerator IEnumerable.GetEnumerator()
406  {
407  return GetEnumerator();
408  }
409 
410  public void CopyTo(TKey[] array, int arrayIndex)
411  {
412  throw new NotImplementedException("Implement this as needed");
413  }
414 
415  public int Count
416  {
417  get { return _internalDict.Count + 1; }
418  }
419 
420  public bool IsReadOnly
421  {
422  get { return true; }
423  }
424 
425  #region Explicit Interface Definitions
426  bool ICollection<TKey>.Contains(TKey item)
427  {
428  throw new NotSupportedException();
429  }
430 
431  void ICollection<TKey>.Add(TKey item)
432  {
433  throw new NotSupportedException();
434  }
435 
436  void ICollection<TKey>.Clear()
437  {
438  throw new NotSupportedException();
439  }
440 
441  bool ICollection<TKey>.Remove(TKey item)
442  {
443  throw new NotSupportedException();
444  }
445  #endregion
446  }
447  #endregion
448  }
449 }