兼具 List 和 Map 的“容器”类 ListMap

来源:互联网 发布:特朗普访华知乎 编辑:程序博客网 时间:2024/06/10 19:36

“容器”两个字之所以打上引号,是因为这个类没有实现 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 == nullreturn 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 - fromIndex
  248.      *
  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 == nullreturn 0;
  293.                 if (c1 == nullreturn -1;
  294.                 if (c2 == nullreturn 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 == nullreturn 0;
  309.                 if (c1 == nullreturn -1;
  310.                 if (c2 == nullreturn 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. }