9
9
import java .util .Set ;
10
10
import java .util .function .Function ;
11
11
12
+ import org .apache .commons .collections4 .MultiValuedMap ;
13
+ import org .apache .commons .collections4 .multimap .ArrayListValuedHashMap ;
14
+
12
15
import lombok .Getter ;
13
16
import lombok .experimental .Accessors ;
14
17
@@ -33,6 +36,10 @@ public class DataTable<T> {
33
36
private HashMap <String , Function <T , Boolean >> filters = new HashMap <>();
34
37
private HashMap <String , DataMap <Object , T >> maps = new HashMap <>();
35
38
39
+ private HashMap <String , Function <T , Object >> multiKeySuppliers = new HashMap <>();
40
+ private HashMap <String , Function <T , Boolean >> multiFilters = new HashMap <>();
41
+ private HashMap <String , MultiValuedMap <Object , T >> multiMaps = new HashMap <>();
42
+
36
43
public DataTable (final Class <T > clazz , final int maxEntries ) {
37
44
this .clazz = clazz ;
38
45
this .maxEntries = maxEntries ;
@@ -43,13 +50,27 @@ public <K> DataTable<T> addIndex(final String name, final Function<T, K> keySupp
43
50
return addIndex (name , keySupplier , null );
44
51
}
45
52
53
+ public <K > DataTable <T > addMultiIndex (final String name , final Function <T , K > keySupplier ) {
54
+ return addMultiIndex (name , keySupplier , null );
55
+ }
56
+
46
57
@ SuppressWarnings ("unchecked" )
47
58
public <K > DataTable <T > addIndex (final String name , final Function <T , K > keySupplier ,
48
59
final Function <T , Boolean > filter ) {
49
60
keySuppliers .put (name , (Function <T , Object >) keySupplier );
50
61
if (filter != null )
51
62
filters .put (name , filter );
52
- maps .put (name , new DataMap <Object , T >(maxEntries ));
63
+ maps .put (name , new DataMap <>(maxEntries ));
64
+ return this ;
65
+ }
66
+
67
+ @ SuppressWarnings ("unchecked" )
68
+ public <K > DataTable <T > addMultiIndex (final String name , final Function <T , K > keySupplier ,
69
+ final Function <T , Boolean > filter ) {
70
+ multiKeySuppliers .put (name , (Function <T , Object >) keySupplier );
71
+ if (filter != null )
72
+ multiFilters .put (name , filter );
73
+ multiMaps .put (name , new ArrayListValuedHashMap <>(maxEntries ));
53
74
return this ;
54
75
}
55
76
@@ -77,6 +98,11 @@ public synchronized T poll() {
77
98
DataMap <Object , T > map = maps .get (name );
78
99
map .remove (func .apply (e ));
79
100
}
101
+ for (String name : multiKeySuppliers .keySet ()) {
102
+ Function <T , ?> func = multiKeySuppliers .get (name );
103
+ MultiValuedMap <Object , T > map = multiMaps .get (name );
104
+ map .removeMapping (func .apply (e ), e );
105
+ }
80
106
return e ;
81
107
}
82
108
@@ -92,6 +118,18 @@ public synchronized <K> T get(final String name, final K key) {
92
118
return maps .get (name ).get (key );
93
119
}
94
120
121
+ /**
122
+ * Gets elements by a specified multi-index.
123
+ *
124
+ * @param <K> the type of the key used by the given multi-index
125
+ * @param name the name of the multi-index
126
+ * @param key the key of the element to retrieve using the given multi-index
127
+ * @return the collection of elements to retrieve, that may be empty
128
+ */
129
+ public synchronized <K > Collection <T > multiGet (final String name , final K key ) {
130
+ return multiMaps .get (name ).get (key );
131
+ }
132
+
95
133
/**
96
134
* Adds one or more elements to the DataTable.
97
135
* <p>
@@ -113,6 +151,14 @@ public synchronized void add(final T... elements) {
113
151
map .put (key , element );
114
152
}
115
153
}
154
+ for (Entry <String , Function <T , Object >> entry : multiKeySuppliers .entrySet ()) {
155
+ Function <T , Boolean > filter = multiFilters .get (entry .getKey ());
156
+ MultiValuedMap <Object , T > map = multiMaps .get (entry .getKey ());
157
+ if (filter == null || filter .apply (element )) {
158
+ Object key = entry .getValue ().apply (element );
159
+ map .put (key , element );
160
+ }
161
+ }
116
162
}
117
163
}
118
164
@@ -128,6 +174,18 @@ public synchronized <K> Set<K> keySet(final String name) {
128
174
return (Set <K >) maps .get (name ).keySet ();
129
175
}
130
176
177
+ /**
178
+ * Get a set of keys for a given multi-index.
179
+ *
180
+ * @param <K> the type of the key for the given multi-index
181
+ * @param name the name of the multi-index to get the keys from
182
+ * @return a set of keys
183
+ */
184
+ @ SuppressWarnings ("unchecked" )
185
+ public synchronized <K > Set <K > multiKeySet (final String name ) {
186
+ return (Set <K >) multiMaps .get (name ).keySet ();
187
+ }
188
+
131
189
/**
132
190
* Get a list of keys for a given index.
133
191
*
@@ -142,6 +200,20 @@ public synchronized <K> List<K> keyList(final String name) {
142
200
return list ;
143
201
}
144
202
203
+ /**
204
+ * Get a list of keys for a given multi-index.
205
+ *
206
+ * @param <K> the type of the key for the given multi-index
207
+ * @param name the name of the multi-index to get the keys from
208
+ * @return a list of keys
209
+ */
210
+ @ SuppressWarnings ("unchecked" )
211
+ public synchronized <K > List <K > multiKeyList (final String name ) {
212
+ List <K > list = new ArrayList <>();
213
+ list .addAll ((Set <K >) multiMaps .get (name ).keySet ());
214
+ return list ;
215
+ }
216
+
145
217
public synchronized Collection <T > values (final String name ) {
146
218
return maps .get (name ).values ();
147
219
}
@@ -174,6 +246,14 @@ public synchronized DataTable<T> load(T[] backingArray) {
174
246
if (filter == null || filter .apply (s ))
175
247
map .put (entry .getValue ().apply (s ), s );
176
248
}
249
+ for (Entry <String , Function <T , Object >> entry : multiKeySuppliers .entrySet ()) {
250
+ MultiValuedMap <Object , T > map = new ArrayListValuedHashMap <>(maxEntries );
251
+ multiMaps .put (entry .getKey (), map );
252
+ Function <T , Boolean > filter = multiFilters .get (entry .getKey ());
253
+ for (T s : backingArray )
254
+ if (filter == null || filter .apply (s ))
255
+ map .put (entry .getValue ().apply (s ), s );
256
+ }
177
257
return this ;
178
258
}
179
259
0 commit comments