Java集合(3):使用Abstract类

Java集合(3):使用Abstract类

每个java.util容器都有其自己的Abstract类,它们提供了该容器接口的部分实现。下面是一个定制自己的Map的例子(List set就省略了):

定制自己的Map实现AbstractMap-->Map,需要实现[Set<Map.Entry<K,V>> entrySet()]方法

实现[Set<Map.Entry<K,V>> entrySet()]方法分两步:

(1) 实现Set<E>接口

(2) 实现Map.Entry<K,V>接口

  1 import java.util.AbstractMap;
  2 import java.util.AbstractSet;
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.HashSet;
  6 import java.util.Hashtable;
  7 import java.util.Iterator;
  8 import java.util.LinkedHashMap;
  9 import java.util.LinkedHashSet;
 10 import java.util.LinkedList;
 11 import java.util.List;
 12 import java.util.Map;
 13 import java.util.Set;
 14 import java.util.TreeMap;
 15 import java.util.TreeSet;
 16 
 17 class Countries {
 18     public static final String[][] DATA = {
 19             // Africa
 20             { "SOUTH AFRICA", "Cape Town" }, { "SUDAN", "Khartoum" },
 21             // Asia
 22             { "CHINA", "Beijing" }, { "JAPAN", "Tokyo" }, { "SOUTH KOREA", "Seoul" },
 23             // Australia and Oceania
 24             { "AUSTRALIA", "Canberra" }, { "NEW ZEALAND", "Wellington" },
 25             // Europe
 26             { "UNITED KINGDOM", "London" }, { "FRANCE", "Paris" }, { "GERMANY", "Berlin" }, { "ITALY", "Rome" },
 27             { "SPAIN", "Madrid" },
 28             // North and Central America
 29             { "UNITED STATES OF AMERICA", "Washington, D.C." }, { "CANADA", "Ottawa" },
 30             // South America
 31             { "BRAZIL", "Brasilia" }, { "ARGENTINA", "Buenos Aires" } };
 32 
 33     private static class FlyweightMap extends AbstractMap<String, String> {
 34 
 35         private final int dataLength;
 36 
 37         private static Set<Map.Entry<String, String>> entries = new EntrySet(DATA.length);
 38 
 39         public FlyweightMap() {
 40             dataLength = 0;
 41         }
 42 
 43         public FlyweightMap(int dataLength) {
 44             this.dataLength = dataLength;
 45         }
 46 
 47         @Override
 48         public Set<Map.Entry<String, String>> entrySet() {
 49             if (dataLength > 0) {
 50                 return new EntrySet(dataLength);
 51             }
 52             return entries;
 53         }
 54 
 55         // (1) 实现Set<E>接口
 56         // 定制自己的Set实现AbstractSet(AbstractCollection)-->Set, 需要实现[Iterator<E> iterator() & int size()]方法
 57         private static class EntrySet extends AbstractSet<Map.Entry<String, String>> {
 58             private int size;
 59 
 60             EntrySet(int size) {
 61                 this.size = size < 0 ? (this.size = 0)
 62                         : (size > DATA.length ? (this.size = DATA.length) : (this.size = size));
 63             }
 64 
 65             @Override
 66             public int size() {
 67                 return size;
 68             }
 69 
 70             @Override
 71             public Iterator<Map.Entry<String, String>> iterator() {
 72                 return new Iterator<Map.Entry<String, String>>() {
 73                     // Only one Entry object per Iterator:
 74                     private Entry entry = new Entry(-1);
 75 
 76                     @Override
 77                     public boolean hasNext() {
 78                         return entry.index < size - 1;
 79                     }
 80 
 81                     @Override
 82                     public java.util.Map.Entry<String, String> next() {
 83                         entry.index++;
 84                         return entry;
 85                     }
 86                 };
 87             }
 88         }
 89 
 90         // (2) 实现Map.Entry<K,V>接口
 91         // 定制自己的Map.Entry实现Map.Entry<K, V>接口, 需要实现下面的方法
 92         // 每个Map.Entry对象都只存了它们的索引,而不是实际的键值。当调用getKey(), getValue()时,才会用索引返回恰当的元素
 93         private static class Entry implements Map.Entry<String, String> {
 94             int index;
 95 
 96             Entry(int index) {
 97                 this.index = index;
 98             }
 99 
100             @Override
101             public boolean equals(Object o) {
102                 return DATA[index][0].equals(o);
103             }
104 
105             @Override
106             public String getKey() {
107                 return DATA[index][0];
108             }
109 
110             @Override
111             public String getValue() {
112                 return DATA[index][1];
113             }
114 
115             @Override
116             public String setValue(String value) {
117                 throw new UnsupportedOperationException();
118             }
119 
120             @Override
121             public int hashCode() {
122                 return DATA[index][0].hashCode();
123             }
124         }
125     }
126 
127     // 取Map全部内容
128     public static Map<String, String> capitals() {
129         return selectAll();
130     }
131 
132     // 取Map全部内容的key
133     public static List<String> names() {
134         return new ArrayList<String>(capitals().keySet());
135     }
136 
137     // 取Map部分内容
138     public static Map<String, String> capitals(final int size) {
139         return select(size);
140     }
141 
142     // 取Map部分内容的key
143     public static List<String> names(int size) {
144         return new ArrayList<String>(select(size).keySet());
145     }
146 
147     private static Map<String, String> selectAll() {
148         return new FlyweightMap();
149     }
150 
151     private static Map<String, String> select(final int size) {
152         return new FlyweightMap(size);
153     }
154 }
155 
156 public class Test4 {
157     public static void main(String[] args) {
158         System.out.println(Countries.capitals(5)); // {SOUTH AFRICA=Cape Town, SUDAN=Khartoum, CHINA=Beijing, JAPAN=Tokyo, SOUTH KOREA=Seoul}
159         System.out.println(Countries.names(5)); // [SOUTH AFRICA, SUDAN, CHINA, JAPAN, SOUTH KOREA]
160         System.out.println(new HashMap<String, String>(Countries.capitals(3))); // {SUDAN=Khartoum, CHINA=Beijing, SOUTH AFRICA=Cape Town}
161         System.out.println(new LinkedHashMap<String, String>(Countries.capitals(3))); // {SOUTH AFRICA=Cape Town, SUDAN=Khartoum, CHINA=Beijing}
162         System.out.println(new TreeMap<String, String>(Countries.capitals(3))); // {CHINA=Beijing, SOUTH AFRICA=Pretoria/Cape Town, SUDAN=Khartoum}
163         System.out.println(new Hashtable<String, String>(Countries.capitals(3))); // {SUDAN=Khartoum, SOUTH AFRICA=Pretoria/Cape Town, CHINA=Beijing}
164         System.out.println(new HashSet<String>(Countries.names(4))); // [SUDAN, CHINA, SOUTH AFRICA, JAPAN]
165         System.out.println(new LinkedHashSet<String>(Countries.names(4))); // [SOUTH AFRICA, SUDAN, CHINA, JAPAN]
166         System.out.println(new TreeSet<String>(Countries.names(4))); // [CHINA, JAPAN, SOUTH AFRICA, SUDAN]
167         System.out.println(new ArrayList<String>(Countries.names(4))); // [SOUTH AFRICA, SUDAN, CHINA, JAPAN]
168         System.out.println(new LinkedList<String>(Countries.names(4))); // [SOUTH AFRICA, SUDAN, CHINA, JAPAN]
169         System.out.println(Countries.capitals().get("BRAZIL")); // Brasilia
170     }
171 }