1. /*
  2. * Copyright 2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.collections.map;
  17. import java.io.IOException;
  18. import java.io.ObjectInputStream;
  19. import java.io.ObjectOutputStream;
  20. import java.io.Serializable;
  21. import java.util.Map;
  22. /**
  23. * A case-insensitive <code>Map</code>.
  24. * <p>
  25. * As entries are added to the map, keys are converted to all lowercase. A new
  26. * key is compared to existing keys by comparing <code>newKey.toString().toLower()</code>
  27. * to the lowercase values in the current <code>KeySet.</code>
  28. * <p>
  29. * Null keys are supported.
  30. * <p>
  31. * The <code>keySet()</code> method returns all lowercase keys, or nulls.
  32. * <p>
  33. * Example:
  34. * <pre><code>
  35. * Map map = new CaseInsensitiveMap();
  36. * map.put("One", "One");
  37. * map.put("Two", "Two");
  38. * map.put(null, "Three");
  39. * map.put("one", "Four");
  40. * </code></pre>
  41. * creates a <code>CaseInsensitiveMap</code> with three entries.<br>
  42. * <code>map.get(null)</code> returns <code>"Three"</code> and <code>map.get("ONE")</code>
  43. * returns <code>"Four".</code> The <code>Set</code> returned by <code>keySet()</code>
  44. * equals <code>{"one", "two", null}.</code>
  45. *
  46. * @since Commons Collections 3.0
  47. * @version $Revision: 1.4 $ $Date: 2004/02/18 01:13:19 $
  48. *
  49. * @author Commons-Collections team
  50. */
  51. public class CaseInsensitiveMap extends AbstractHashedMap implements Serializable, Cloneable {
  52. /** Serialisation version */
  53. private static final long serialVersionUID = -7074655917369299456L;
  54. /**
  55. * Constructs a new empty map with default size and load factor.
  56. */
  57. public CaseInsensitiveMap() {
  58. super(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_THRESHOLD);
  59. }
  60. /**
  61. * Constructs a new, empty map with the specified initial capacity.
  62. *
  63. * @param initialCapacity the initial capacity
  64. * @throws IllegalArgumentException if the initial capacity is less than one
  65. */
  66. public CaseInsensitiveMap(int initialCapacity) {
  67. super(initialCapacity);
  68. }
  69. /**
  70. * Constructs a new, empty map with the specified initial capacity and
  71. * load factor.
  72. *
  73. * @param initialCapacity the initial capacity
  74. * @param loadFactor the load factor
  75. * @throws IllegalArgumentException if the initial capacity is less than one
  76. * @throws IllegalArgumentException if the load factor is less than zero
  77. */
  78. public CaseInsensitiveMap(int initialCapacity, float loadFactor) {
  79. super(initialCapacity, loadFactor);
  80. }
  81. /**
  82. * Constructor copying elements from another map.
  83. * <p>
  84. * Keys will be converted to lower case strings, which may cause
  85. * some entries to be removed (if string representation of keys differ
  86. * only by character case).
  87. *
  88. * @param map the map to copy
  89. * @throws NullPointerException if the map is null
  90. */
  91. public CaseInsensitiveMap(Map map) {
  92. super(map);
  93. }
  94. //-----------------------------------------------------------------------
  95. /**
  96. * Overrides convertKey() from {@link AbstractHashedMap} to convert keys to
  97. * lower case.
  98. * <p>
  99. * Returns null if key is null.
  100. *
  101. * @param key the key convert
  102. * @return the converted key
  103. */
  104. protected Object convertKey(Object key) {
  105. if (key != null) {
  106. return key.toString().toLowerCase();
  107. } else {
  108. return AbstractHashedMap.NULL;
  109. }
  110. }
  111. //-----------------------------------------------------------------------
  112. /**
  113. * Clones the map without cloning the keys or values.
  114. *
  115. * @return a shallow clone
  116. */
  117. public Object clone() {
  118. return super.clone();
  119. }
  120. /**
  121. * Write the map out using a custom routine.
  122. */
  123. private void writeObject(ObjectOutputStream out) throws IOException {
  124. out.defaultWriteObject();
  125. doWriteObject(out);
  126. }
  127. /**
  128. * Read the map in using a custom routine.
  129. */
  130. private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
  131. in.defaultReadObject();
  132. doReadObject(in);
  133. }
  134. }