annotate src/goodjava/util/CacheMap.java @ 1542:d4407e8de707

disallow duplicates in table constructor
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 20 Sep 2020 15:53:58 -0600
parents 1b809d2fdf03
children fa066aaa068c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1498
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
1 package goodjava.util;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
2
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
3 import java.lang.ref.ReferenceQueue;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
4 import java.util.Map;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
5 import java.util.AbstractMap;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
6 import java.util.HashMap;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
7 import java.util.Set;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
8 import java.util.AbstractSet;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
9 import java.util.Iterator;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
10
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
11
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
12 public abstract class CacheMap<K,V> extends AbstractMap<K,V> {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
13
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
14 protected static interface MyReference<K,V> {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
15 public K key();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
16 public V get();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
17 public void clear();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
18 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
19
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
20 protected abstract MyReference<K,V> newReference(K key,V value,ReferenceQueue<V> q);
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
21
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
22 private final Map<K,MyReference<K,V>> cache = new HashMap<K,MyReference<K,V>>();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
23 private final ReferenceQueue<V> queue = new ReferenceQueue<V>();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
24
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
25 private void sweep() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
26 while(true) {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
27 @SuppressWarnings("unchecked")
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
28 MyReference<K,V> ref = (MyReference<K,V>)queue.poll();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
29 if( ref == null )
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
30 return;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
31 MyReference<K,V> mappedRef = cache.remove(ref.key());
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
32 if( mappedRef != ref && mappedRef != null )
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
33 cache.put( mappedRef.key(), mappedRef ); // put it back
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
34 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
35 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
36
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
37 public int size() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
38 return cache.size();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
39 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
40
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
41 public boolean isEmpty() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
42 return cache.isEmpty();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
43 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
44
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
45 public boolean containsKey(Object key) {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
46 return cache.containsKey(key);
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
47 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
48
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
49 public V get(Object key) {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
50 MyReference<K,V> ref = cache.get(key);
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
51 return ref==null ? null : ref.get();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
52 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
53
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
54 public V put(K key,V value) {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
55 sweep();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
56 MyReference<K,V> ref = cache.put( key, newReference(key,value,queue) );
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
57 return ref==null ? null : ref.get();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
58 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
59
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
60 public V remove(Object key) {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
61 sweep();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
62 MyReference<K,V> ref = cache.remove(key);
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
63 return ref==null ? null : ref.get();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
64 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
65
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
66 public void clear() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
67 sweep();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
68 cache.clear();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
69 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
70
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
71 /*
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
72 public Object clone() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
73 GCCacheMap map = new GCCacheMap();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
74 map.cache = (HashMap)cache.clone();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
75 return map;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
76 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
77 */
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
78 public Set<K> keySet() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
79 return cache.keySet();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
80 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
81
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
82 public Set<Map.Entry<K,V>> entrySet() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
83 return new MySet();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
84 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
85
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
86
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
87 private class MySet extends AbstractSet<Map.Entry<K,V>> {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
88
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
89 public int size() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
90 return CacheMap.this.size();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
91 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
92
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
93 public Iterator<Map.Entry<K,V>> iterator() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
94 return new MyIterator(cache.entrySet().iterator());
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
95 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
96
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
97 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
98
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
99 private class MyIterator implements Iterator<Map.Entry<K,V>> {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
100 Iterator<Map.Entry<K,MyReference<K,V>>> iter;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
101
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
102 MyIterator(Iterator<Map.Entry<K,MyReference<K,V>>> iter) {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
103 this.iter = iter;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
104 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
105
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
106 public boolean hasNext() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
107 return iter.hasNext();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
108 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
109
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
110 public void remove() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
111 iter.remove();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
112 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
113
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
114 public Map.Entry<K,V> next() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
115 return new MyEntry( iter.next() );
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
116 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
117 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
118
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
119 private class MyEntry implements Map.Entry<K,V> {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
120 Map.Entry<K,MyReference<K,V>> entry;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
121
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
122 MyEntry(Map.Entry<K,MyReference<K,V>> entry) {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
123 this.entry = entry;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
124 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
125
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
126 public K getKey() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
127 return entry.getKey();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
128 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
129
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
130 public V getValue() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
131 MyReference<K,V> ref = entry.getValue();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
132 return ref.get();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
133 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
134
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
135 public V setValue(V value) {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
136 MyReference<K,V> ref = entry.setValue( newReference(getKey(),value,queue) );
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
137 return ref.get();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
138 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
139
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
140 public boolean equals(Object o) {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
141 if( o==null || !(o instanceof CacheMap.MyEntry) )
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
142 return false;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
143 @SuppressWarnings("unchecked")
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
144 MyEntry m = (MyEntry)o;
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
145 return entry.equals(m.entry);
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
146 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
147
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
148 public int hashCode() {
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
149 K key = getKey();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
150 V value = getValue();
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
151 return (key==null ? 0 : key.hashCode()) ^
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
152 (value==null ? 0 : value.hashCode());
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
153 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
154 }
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
155
1b809d2fdf03 add CacheMap
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
156 }