“容器”两个字之所以打上引号,是因为这个类没有实现 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.}
你在无垠的海边第一次听到了自己心跳的声音,