UnionMap extends AbstractMap<K, V> { @Override public int size() { if (size >= 0) { return size; } final Map<K, V> a; final Map<K, V> b; if (first.size() >= second.size()) { a = first; b = second; } else { a = second; b = first; } int size = a.size(); if (!b.isEmpty()) { for (K k : b.keySet()) { if (!a.containsKey(k)) { size++; } } } return this.size = size; } UnionMap(Map<K, V> first, Map<K, V> second); @Override int size(); @Override boolean isEmpty(); @Override boolean containsKey(Object key); @Override boolean containsValue(Object value); @Override V get(Object key); @Override V put(K key, V value); @Override V remove(Object key); @Override void clear(); @Override Set<Entry<K, V>> entrySet();  }
@Test void testSize() { assertThat(new UnionMap<>(of("1", "a"), of("2", "b"))).hasSize(2); assertThat(new UnionMap<>(of("1", "a", "2", "b"), of("1", "b"))).hasSize(2); assertThat(new UnionMap<>(of("1", "a"), of("1", "b", "2", "b"))).hasSize(2); }