1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.nuiton.util;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.LinkedHashMap;
34 import java.util.Map;
35 import java.util.Set;
36
37
38
39
40
41 public class LRUMapMultiKey extends LinkedHashMap<LRUMapMultiKey.Key, Object> {
42
43 private static final long serialVersionUID = 1L;
44
45 private static final Log log = LogFactory.getLog(LRUMapMultiKey.class);
46
47
48 public static class Key extends ArrayList<Object> {
49
50 private static final long serialVersionUID = 1L;
51
52
53
54 protected int hash = 0;
55
56 public Key(Object... k) {
57 Collections.addAll(this, k);
58 }
59
60 @Override
61 public int hashCode() {
62 if (hash == 0) {
63 hash = super.hashCode();
64 }
65 return hash;
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 }
107
108
109 protected Map<Object, Set<Key>> keys = new HashMap<Object, Set<Key>>();
110
111 protected int maxSize;
112
113 public LRUMapMultiKey(int maxSize) {
114 super(maxSize <= 0 ? 1000 : maxSize * 100 / 75, (float) 0.75, true);
115 this.maxSize = maxSize;
116 }
117
118 public Key createKey(Object... k) {
119 return new Key(k);
120 }
121
122
123
124
125 @Override
126 public void clear() {
127 keys.clear();
128 super.clear();
129 }
130
131
132
133
134 @Override
135 public Object remove(Object k) {
136 if (k instanceof Key) {
137 return super.remove(k);
138 } else {
139 ArrayList<Key> result = new ArrayList<Key>();
140 Set<Key> list = keys.remove(k);
141 if (list != null) {
142 for (Iterator<Key> i = list.iterator(); i.hasNext(); ) {
143 Key key = i.next();
144 result.add(key);
145 super.remove(key);
146 }
147 list.clear();
148 }
149 return result;
150 }
151 }
152
153
154
155
156 @Override
157 public Object put(Key key, Object value) {
158
159
160
161
162 for (Iterator i = key.iterator(); i.hasNext(); ) {
163 Object k = i.next();
164 Set<Key> list = keys.get(k);
165 if (list == null) {
166 list = new HashSet<Key>();
167 keys.put(k, list);
168 }
169 list.add(key);
170
171 }
172
173 Object result = super.put(key, value);
174
175 return result;
176 }
177
178
179
180
181 @Override
182 protected boolean removeEldestEntry(Map.Entry<Key, Object> eldest) {
183 if (this.maxSize > 0 && size() > this.maxSize) {
184 Key key = eldest.getKey();
185 for (Iterator i = key.iterator(); i.hasNext(); ) {
186 Object k = i.next();
187 Set<Key> list = keys.get(k);
188 if (list != null) {
189 list.remove(key);
190 if (list.size() == 0) {
191 keys.remove(k);
192 }
193 }
194 }
195
196 if (!containsKey(eldest.getKey())) {
197 log.warn("possible memory leak !!! removeEldestEntry (" + eldest.getKey().getClass() + ")" + eldest.getKey() + " size " + size() + " maxSize" + maxSize);
198 }
199 return true;
200 }
201 return false;
202 }
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223 }
224
225