兼具List和Map的“容器”类ListMap2011-06-12 csdn博客 YidingHe“容器”两个字之所以打上引号,是因为这个类没有实现 Collection 接口。要写一个兼具 List 功能和 Map 功能的类,有几个困难,一 是 Java 不允许同时实现 List 和 Map 两个接口,二是这个 ListMap 结合了二 者的功能之后,产生了特殊的接口。例如 Collection 的 contains 方法,在 ListMap 中就需要衍生出 containsKey 和 containsValue 两个方法,分别判断 容器中是否存在指定的键和值。下面是我的实现(有什么 BUG 欢迎指正):
1.package myCollections;2. 3.import java.util.*;4. 5./**6. * 兼具 List 和 Map 功能的容器类7. */8.@SuppressWarnings({"unchecked"})9.public class ListMap<K, V> {10. 11.private List<Item> values = new ArrayList<Item>();12. 13./**14. * 获取元素个数15. *16. * @return 元素个数17. */18.public int size() {19.return values.size();20.}21. 22./**23. * 判断容器是否为空24. *25. * @return 如果为空则返回 true。26. */27.public boolean isEmpty() {28.return values.isEmpty();29.}30. 31./**32. * 获得一个值迭代器33. *34. * @return 值迭代器35. */36.public Iterator<V> iterator() {37.return values().iterator();38.}39. 40./**41. * 获得一个值数组42. *43. * @return 值数组44. */45.public V[] toArray() {46.Object[] arr = new Object[values.size()];47.for (int i = 0; i < values.size(); i++) {48.arr[i] = values.get(i).value;49.}50.return (V[]) arr;51.}52. 53./**54. * 检查指定的键是否存在55. *56. * @param key 键57. *58. * @return 如果存在则返回 true。59. */60.public boolean containsKey(K key) {61.if (key == null) return false;62.for (Item item : values) {63.if (item.key.equals(key)) {64.return true;65.}66.}67.return false;68.}69. 70./**71. * 检查指定的值是否存在72. *73. * @param value 值74. *75. * @return 如果存在则返回 true。76. */77.public boolean containsValue(V value) {78.for (Item item : values) {79.if (item.value.equals(value)) {80.return true;81.}82.}83.return false;84.}85. 86./**87. * 通过键获得值88. *89. * @param key 键90. *91. * @return 值92. */93.public V get(K key) {94.for (Item item : values) {95.if (item.key.equals(key)) {96.return item.value;97.}98.}99.return null;100.}101. 102./**103. * 设置值。如果键不存在则添加。104. *105. * @param key 键106. * @param value 值107. *108. * @return 原来的值。如果键不存在则返回 null。109. */110.// 这里要注意,key 必须是唯一的,所以如果 key 已经存在则做替换,否则做添加111.public V put(K key, V value) {112.for (Item item : values) {113.if (item.key.equals(key)) {114.V replaced = item.value;115.item.value = value;116.return replaced;117.}118.}119. 120.Item item = new Item(key, value);121.values.add(item);122.return null;123.}124. 125./**126. * 删除键。值也会删除。127. *128. * @param key 键129. *130. * @return 如果键存在则返回 true。131. */132.public boolean remove(K key) {133.for (Item item : values) {134.if (item.key.equals(key)) {135.values.remove(item);136.return true;137.}138.}139.return false;140.}141. 142./**143. * 删除指定位置的键和值144. *145. * @param index 位置146. *147. * @return 该位置的值148. *149. * @throws IndexOutOfBoundsException 如果位置超过范围150. */151.public V remove(int index) {152.return values.remove(index).value;153.}154. 155./**156. * 清除容器中的所有键和值157. */158.public void clear() {159.values.clear();160.}161. 162./**163. * 获取指定位置上的值164. *165. * @param index 位置166. *167. * @return 值168. *169. * @throws IndexOutOfBoundsException 如果位置超过范围170. */171.public V get(int index) {172.return values.get(index).value;173.}174. 175./**176. * 设置指定位置的值177. *178. * @param index 位置179. * @param value 新的值180. *181. * @return 旧的值182. *183. * @throws IndexOutOfBoundsException 如果位置超过范围184. */185.public V set(int index, V value) {186.Item item = values.get(index);187.V old_value = item.value;188.item.value = value;189.return old_value;190.}191. 192./**193. * 在指定位置添加一个新的键和值194. *195. * @param index 位置196. * @param key 键197. * @param value 值198. *199. * @throws IllegalStateException 如果键已经存在200. */201.public void add(int index, K key, V value) {202.if (containsKey(key)) {203.throw new IllegalStateException("key alreay exists.");204.}205.Item item = new Item(key, value);206.values.add(index, item);207.}208. 209./**210. * 根据值查找所在的第一个位置211. *212. * @param value 值213. *214. * @return 值所在的第一个位置215. */216.public int indexOfValue(V value) {217.for (int i = 0; i < values.size(); i++) {218.Item item = values.get(i);219.if (item.value.equals(value)) {220.return i;221.}222.}223.return -1;224.}225. 226./**227. * 根据键查找所在位置228. *229. * @param key 键230. *231. * @return 键所在位置232. */233.public int indexOfKey(K key) {234.if (key == null) {235.return -1;236.}237.for (int i = 0; i < values.size(); i++) {238.Item item = values.get(i);239.if (item.key.equals(key)) {240.return i;241.}242.}243.return -1;244.} 245. 246./**247. * 获取一个包含元素子集和的容器。容器的元素个数为 toIndex - fromIndex248. *249. * @param fromIndex 子集和的开始位置(含)250. * @param toIndex 子集和的结束位置(不含)251. *252. * @return 包含元素子集和的容器253. */254.public ListMap subList(int fromIndex, int toIndex) {255.ListMap<K, V> map = new ListMap<K, V>();256.map.values.addAll(values.subList(fromIndex, toIndex));257.return map;258.}259. 260./**261. * 获取值 List 对象262. * @return 包含值的 List 对象263. */264.public List<V> values() {265.List<V> list = new ArrayList<V>();266.for (Item item : values) {267.list.add(item.value);268.}269.return list;270.}271. 272./**273. * 获取包含键的 List 对象274. * @return 包含键的 List 对象275. */276.public List<K> keys() {277.List<K> list = new ArrayList<K>();278.for (Item item : values) {279.list.add(item.key);280.}281.return list;282.}283. 284./**285. * 对键进行从小到大排序286. */287.public void sortKey() {288.Collections.sort(values, new Comparator<Item>() {289.public int compare(Item i1, Item i2) {290.Comparable c1 = (Comparable) i1.key;291.Comparable c2 = (Comparable) i2.key;292.if (c1 == null && c2 == null) return 0;293.if (c1 == null) return -1;294.if (c2 == null) return 1;295.return c1.compareTo(c2);296.}297.});298.}299. 300./**301. * 对值进行从小到大排序302. */303.public void sortValue() {304.Collections.sort(values, new Comparator<Item>() {305.public int compare(Item i1, Item i2) {306.Comparable c1 = (Comparable) i1.value;307.Comparable c2 = (Comparable) i2.value;308.if (c1 == null && c2 == null) return 0;309.if (c1 == null) return -1;310.if (c2 == null) return 1;311.return c1.compareTo(c2);312.}313.});314.}315. 316./**317. * 对容器元素进行倒排318. */319.public void reverse() {320.Collections.reverse(values);321.}322. 323./**324. * 内部类325. */326.private class Item {327. 328.public K key;329. 330.public V value;331. 332.public Item(K key, V value) {333.if (key == null) {334.throw new NullPointerException("key cannot be null.");335.}336.this.key = key;337.this.value = value;338.}339.}340.}