View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.map;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertNull;
22  import static org.junit.jupiter.api.Assertions.assertSame;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  import static org.junit.jupiter.api.Assertions.fail;
26  
27  import java.util.Map;
28  import java.util.concurrent.atomic.AtomicReference;
29  
30  import org.apache.commons.collections4.MapIterator;
31  import org.apache.commons.collections4.keyvalue.MultiKey;
32  import org.junit.jupiter.api.Test;
33  
34  /**
35   * JUnit tests.
36   *
37   * @param <K> the key type.
38   * @param <V> the value type.
39   */
40  public class MultiKeyMapTest<K, V> extends AbstractIterableMapTest<MultiKey<? extends K>, V> {
41  
42      static final Integer I1 = Integer.valueOf(1);
43      static final Integer I2 = Integer.valueOf(2);
44      static final Integer I3 = Integer.valueOf(3);
45      static final Integer I4 = Integer.valueOf(4);
46      static final Integer I5 = Integer.valueOf(5);
47      static final Integer I6 = Integer.valueOf(6);
48      static final Integer I7 = Integer.valueOf(7);
49      static final Integer I8 = Integer.valueOf(8);
50  
51      @Override
52      public String getCompatibilityVersion() {
53          return "4";
54      }
55  
56      /**
57       * {@inheritDoc}
58       */
59      @Override
60      public MultiKeyMap<K, V> getMap() {
61          return (MultiKeyMap<K, V>) super.getMap();
62      }
63  
64      @SuppressWarnings("unchecked")
65      private MultiKey<K>[] getMultiKeyKeys() {
66          return new MultiKey[] {
67              new MultiKey<>(I1, I2),
68              new MultiKey<>(I2, I3),
69              new MultiKey<>(I3, I4),
70              new MultiKey<>(I1, I1, I2),
71              new MultiKey<>(I2, I3, I4),
72              new MultiKey<>(I3, I7, I6),
73              new MultiKey<>(I1, I1, I2, I3),
74              new MultiKey<>(I2, I4, I5, I6),
75              new MultiKey<>(I3, I6, I7, I8),
76              new MultiKey<>(I1, I1, I2, I3, I4),
77              new MultiKey<>(I2, I3, I4, I5, I6),
78              new MultiKey<>(I3, I5, I6, I7, I8),
79          };
80      }
81  
82      @Override
83      @SuppressWarnings("unchecked")
84      public V[] getNewSampleValues() {
85          return (V[]) new Object[] {
86              "1a", "1b", "1c",
87              "2d", "2e", "2f",
88              "3g", "3h", "3i",
89              "4j", "4k", "4l",
90          };
91      }
92  
93      @Override
94      @SuppressWarnings("unchecked")
95      public MultiKey<K>[] getOtherKeys() {
96          return new MultiKey[] {
97              new MultiKey<>(I1, I7),
98              new MultiKey<>(I1, I8),
99              new MultiKey<>(I2, I4),
100             new MultiKey<>(I2, I5),
101         };
102     }
103 
104     @Override
105     public MultiKey<K>[] getSampleKeys() {
106         return getMultiKeyKeys();
107     }
108 
109     @Override
110     @SuppressWarnings("unchecked")
111     public V[] getSampleValues() {
112         return (V[]) new Object[] {
113             "2A", "2B", "2C",
114             "3D", "3E", "3F",
115             "4G", "4H", "4I",
116             "5J", "5K", "5L",
117         };
118     }
119 
120     @Override
121     public boolean isAllowNullKey() {
122         return false;
123     }
124 
125     @Override
126     public MultiKeyMap<K, V> makeObject() {
127         return new MultiKeyMap<>();
128     }
129 
130     @Test
131     @SuppressWarnings("unchecked")
132     public void testClone() {
133         final MultiKeyMap<K, V> map = new MultiKeyMap<>();
134         map.put(new MultiKey<>((K) I1, (K) I2), (V) "1-2");
135         final Map<MultiKey<? extends K>, V> cloned = map.clone();
136         assertEquals(map.size(), cloned.size());
137         assertSame(map.get(new MultiKey<>((K) I1, (K) I2)), cloned.get(new MultiKey<>((K) I1, (K) I2)));
138     }
139 
140     /**
141      * Tests COMPRESS-872
142      * <p>
143      * Claim:
144      * </p>
145      * <ol>
146      * <li>Create a MultiKeyMap, with key(s) of a type (class/record) which has some fields.
147      * <li>Use multiKeyMap.put(T... keys, V value), to create an entry in the Map, to map the keys to a value
148      * <li>Use multiKeyMap.get(T... keys), to verify that the mapping exists and returns the expected value.
149      * <li>Modify/alter any of the objects used as a key. It is enough to change the value of any member field of any of the objects.
150      * <li>Use multiKeyMap.get(T... keys) again, however, now there is no mapping for these keys!
151      * <li>Use multiKeyMap.get(T... keys) with the new modified/altered objects, and it will return the expected value
152      * </ol>
153      */
154     @Test
155     public void testCompress872() {
156         final AtomicReference<String> k1 = new AtomicReference<>("K1v1");
157         final AtomicReference<String> k2 = new AtomicReference<>("K2v1");
158         final MultiKeyMap<AtomicReference<String>, String> map = (MultiKeyMap<AtomicReference<String>, String>) makeObject();
159         assertNull(map.put(k1, k2, "V"));
160         assertEquals("V", map.get(k1, k2));
161         k1.set("K1v2");
162         assertEquals("V", map.get(k1, k2));
163         assertEquals("V", map.get(k1, k2));
164     }
165 
166     @Test
167     @SuppressWarnings("unchecked")
168     public void testLRUMultiKeyMap() {
169         final MultiKeyMap<K, V> map = MultiKeyMap.multiKeyMap(new LRUMap<>(2));
170         map.put((K) I1, (K) I2, (V) "1-2");
171         map.put((K) I1, (K) I3, (V) "1-1");
172         assertEquals(2, map.size());
173         map.put((K) I1, (K) I4, (V) "1-4");
174         assertEquals(2, map.size());
175         assertTrue(map.containsKey(I1, I3));
176         assertTrue(map.containsKey(I1, I4));
177         assertFalse(map.containsKey(I1, I2));
178 
179         final MultiKeyMap<K, V> cloned = map.clone();
180         assertEquals(2, map.size());
181         assertTrue(cloned.containsKey(I1, I3));
182         assertTrue(cloned.containsKey(I1, I4));
183         assertFalse(cloned.containsKey(I1, I2));
184         cloned.put((K) I1, (K) I5, (V) "1-5");
185         assertEquals(2, cloned.size());
186         assertTrue(cloned.containsKey(I1, I4));
187         assertTrue(cloned.containsKey(I1, I5));
188     }
189 
190     @Test
191     public void testMultiKeyContainsKey() {
192         resetFull();
193         final MultiKeyMap<K, V> multimap = getMap();
194         final MultiKey<K>[] keys = getMultiKeyKeys();
195 
196         for (final MultiKey<K> key : keys) {
197             switch (key.size()) {
198             case 2:
199                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
200                 assertFalse(multimap.containsKey(null, key.getKey(1)));
201                 assertFalse(multimap.containsKey(key.getKey(0), null));
202                 assertFalse(multimap.containsKey(null, null));
203                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null));
204                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, null));
205                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, null, null));
206                 break;
207             case 3:
208                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
209                 assertFalse(multimap.containsKey(null, key.getKey(1), key.getKey(2)));
210                 assertFalse(multimap.containsKey(key.getKey(0), null, key.getKey(2)));
211                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null));
212                 assertFalse(multimap.containsKey(null, null, null));
213                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null));
214                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null, null));
215                 break;
216             case 4:
217                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
218                 assertFalse(multimap.containsKey(null, key.getKey(1), key.getKey(2), key.getKey(3)));
219                 assertFalse(multimap.containsKey(key.getKey(0), null, key.getKey(2), key.getKey(3)));
220                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, key.getKey(3)));
221                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null));
222                 assertFalse(multimap.containsKey(null, null, null, null));
223                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
224                 break;
225             case 5:
226                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
227                 assertFalse(multimap.containsKey(null, key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
228                 assertFalse(multimap.containsKey(key.getKey(0), null, key.getKey(2), key.getKey(3), key.getKey(4)));
229                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, key.getKey(3), key.getKey(4)));
230                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null, key.getKey(4)));
231                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
232                 assertFalse(multimap.containsKey(null, null, null, null, null));
233                 break;
234             default:
235                 fail("Invalid key size");
236             }
237         }
238     }
239 
240     @Test
241     public void testMultiKeyGet() {
242         resetFull();
243         final MultiKeyMap<K, V> multimap = getMap();
244         final MultiKey<K>[] keys = getMultiKeyKeys();
245         final V[] values = getSampleValues();
246 
247         for (int i = 0; i < keys.length; i++) {
248             final MultiKey<K> key = keys[i];
249             final V value = values[i];
250 
251             switch (key.size()) {
252             case 2:
253                 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1)));
254                 assertNull(multimap.get(null, key.getKey(1)));
255                 assertNull(multimap.get(key.getKey(0), null));
256                 assertNull(multimap.get(null, null));
257                 assertNull(multimap.get(key.getKey(0), key.getKey(1), null));
258                 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, null));
259                 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, null, null));
260                 break;
261             case 3:
262                 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2)));
263                 assertNull(multimap.get(null, key.getKey(1), key.getKey(2)));
264                 assertNull(multimap.get(key.getKey(0), null, key.getKey(2)));
265                 assertNull(multimap.get(key.getKey(0), key.getKey(1), null));
266                 assertNull(multimap.get(null, null, null));
267                 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null));
268                 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null, null));
269                 break;
270             case 4:
271                 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
272                 assertNull(multimap.get(null, key.getKey(1), key.getKey(2), key.getKey(3)));
273                 assertNull(multimap.get(key.getKey(0), null, key.getKey(2), key.getKey(3)));
274                 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, key.getKey(3)));
275                 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null));
276                 assertNull(multimap.get(null, null, null, null));
277                 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
278                 break;
279             case 5:
280                 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
281                 assertNull(multimap.get(null, key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
282                 assertNull(multimap.get(key.getKey(0), null, key.getKey(2), key.getKey(3), key.getKey(4)));
283                 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, key.getKey(3), key.getKey(4)));
284                 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null, key.getKey(4)));
285                 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
286                 assertNull(multimap.get(null, null, null, null, null));
287                 break;
288             default:
289                 fail("Invalid key size");
290             }
291         }
292     }
293 
294     @Test
295     public void testMultiKeyPut() {
296         final MultiKey<K>[] keys = getMultiKeyKeys();
297         final V[] values = getSampleValues();
298 
299         for (int i = 0; i < keys.length; i++) {
300             final MultiKeyMap<K, V> multimap = new MultiKeyMap<>();
301 
302             final MultiKey<K> key = keys[i];
303             final V value = values[i];
304 
305             switch (key.size()) {
306             case 2:
307                 assertNull(multimap.put(key.getKey(0), key.getKey(1), value));
308                 assertEquals(1, multimap.size());
309                 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1)));
310                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
311                 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1))));
312                 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), null));
313                 assertEquals(1, multimap.size());
314                 assertNull(multimap.get(key.getKey(0), key.getKey(1)));
315                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
316                 break;
317             case 3:
318                 assertNull(multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), value));
319                 assertEquals(1, multimap.size());
320                 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2)));
321                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
322                 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1), key.getKey(2))));
323                 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), null));
324                 assertEquals(1, multimap.size());
325                 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2)));
326                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
327                 break;
328             case 4:
329                 assertNull(multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), value));
330                 assertEquals(1, multimap.size());
331                 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
332                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
333                 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3))));
334                 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
335                 assertEquals(1, multimap.size());
336                 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
337                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
338                 break;
339             case 5:
340                 assertNull(multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4), value));
341                 assertEquals(1, multimap.size());
342                 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
343                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
344                 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4))));
345                 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4), null));
346                 assertEquals(1, multimap.size());
347                 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
348                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
349                 break;
350             default:
351                 fail("Invalid key size");
352             }
353         }
354     }
355 
356     @Test
357     public void testMultiKeyPutWithNullKey() {
358         final MultiKeyMap<String, String> map = new MultiKeyMap<>();
359         map.put("a", null, "value1");
360         map.put("b", null, "value2");
361         map.put("c", null, "value3");
362         map.put("a", "z",  "value4");
363         map.put("a", null, "value5");
364         map.put(null, "a", "value6");
365         map.put(null, null, "value7");
366 
367         assertEquals(6, map.size());
368         assertEquals("value5", map.get("a", null));
369         assertEquals("value4", map.get("a", "z"));
370         assertEquals("value6", map.get(null, "a"));
371     }
372 
373     @Test
374     public void testMultiKeyRemove() {
375         final MultiKey<K>[] keys = getMultiKeyKeys();
376         final V[] values = getSampleValues();
377 
378         for (int i = 0; i < keys.length; i++) {
379             resetFull();
380             final MultiKeyMap<K, V> multimap = getMap();
381             final int size = multimap.size();
382 
383             final MultiKey<K> key = keys[i];
384             final V value = values[i];
385 
386             switch (key.size()) {
387             case 2:
388                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
389                 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1)));
390                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1)));
391                 assertEquals(size - 1, multimap.size());
392                 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1)));
393                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1)));
394                 break;
395             case 3:
396                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
397                 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2)));
398                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
399                 assertEquals(size - 1, multimap.size());
400                 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2)));
401                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
402                 break;
403             case 4:
404                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
405                 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
406                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
407                 assertEquals(size - 1, multimap.size());
408                 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
409                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
410                 break;
411             case 5:
412                 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
413                 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
414                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
415                 assertEquals(size - 1, multimap.size());
416                 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
417                 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
418                 break;
419             default:
420                 fail("Invalid key size");
421             }
422         }
423     }
424 
425     @Test
426     public void testMultiKeyRemoveAll1() {
427         resetFull();
428         final MultiKeyMap<K, V> multimap = getMap();
429         assertEquals(12, multimap.size());
430 
431         multimap.removeAll(I1);
432         assertEquals(8, multimap.size());
433         for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
434             final MultiKey<? extends K> key = it.next();
435             assertFalse(I1.equals(key.getKey(0)));
436         }
437     }
438 
439     @Test
440     public void testMultiKeyRemoveAll2() {
441         resetFull();
442         final MultiKeyMap<K, V> multimap = getMap();
443         assertEquals(12, multimap.size());
444 
445         multimap.removeAll(I2, I3);
446         assertEquals(9, multimap.size());
447         for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
448             final MultiKey<? extends K> key = it.next();
449             assertFalse(I2.equals(key.getKey(0)) && I3.equals(key.getKey(1)));
450         }
451     }
452 
453     @Test
454     public void testMultiKeyRemoveAll3() {
455         resetFull();
456         final MultiKeyMap<K, V> multimap = getMap();
457         assertEquals(12, multimap.size());
458 
459         multimap.removeAll(I1, I1, I2);
460         assertEquals(9, multimap.size());
461         for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
462             final MultiKey<? extends K> key = it.next();
463             assertFalse(I1.equals(key.getKey(0)) && I1.equals(key.getKey(1)) && I2.equals(key.getKey(2)));
464         }
465     }
466 
467 //    public void testCreate() throws Exception {
468 //        resetEmpty();
469 //        writeExternalFormToDisk(
470 //            (java.io.Serializable) map,
471 //            "src/test/resources/data/test/MultiKeyMap.emptyCollection.version4.obj");
472 //        resetFull();
473 //        writeExternalFormToDisk(
474 //            (java.io.Serializable) map,
475 //            "src/test/resources/data/test/MultiKeyMap.fullCollection.version4.obj");
476 //    }
477 
478     @Test
479     public void testMultiKeyRemoveAll4() {
480         resetFull();
481         final MultiKeyMap<K, V> multimap = getMap();
482         assertEquals(12, multimap.size());
483 
484         multimap.removeAll(I1, I1, I2, I3);
485         assertEquals(10, multimap.size());
486         for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
487             final MultiKey<? extends K> key = it.next();
488             assertFalse(I1.equals(key.getKey(0)) && I1.equals(key.getKey(1)) && I2.equals(key.getKey(2)) && key.size() >= 4 && I3.equals(key.getKey(3)));
489         }
490     }
491 
492     @Test
493     @SuppressWarnings("unchecked")
494     public void testNullHandling() {
495         resetFull();
496         assertNull(map.get(null));
497         assertFalse(map.containsKey(null));
498         assertFalse(map.containsValue(null));
499         assertNull(map.remove(null));
500         assertFalse(map.entrySet().contains(null));
501         assertFalse(map.containsKey(null));
502         assertFalse(map.containsValue(null));
503 
504         assertThrows(NullPointerException.class, () -> map.put(null, null));
505 
506         assertNull(map.put(new MultiKey<>(null, null), null));
507 
508         assertThrows(NullPointerException.class, () -> map.put(null, (V) new Object()));
509     }
510 
511 }