MATSIM
ArrayMap.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * *
4  * *********************************************************************** *
5  * *
6  * copyright : (C) 2012 by the members listed in the COPYING, *
7  * LICENSE and WARRANTY file. *
8  * email : info at matsim dot org *
9  * *
10  * *********************************************************************** *
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * See also COPYING, LICENSE and WARRANTY file *
17  * *
18  * *********************************************************************** */
19 
20 package org.matsim.core.utils.collections;
21 
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.NoSuchElementException;
27 import java.util.Objects;
28 import java.util.Set;
29 
41 public class ArrayMap<K, V> implements Map<K, V> {
42 
43  private final static Object[] EMPTY = new Object[0];
44 
45  private Object[] data = EMPTY;
46 
47  public ArrayMap() {
48  }
49 
50  public ArrayMap(Map<K, V> map) {
51  this.data = new Object[map.size() * 2];
52  int i = 0;
53  for (Map.Entry<K, V> e : map.entrySet()) {
54  this.data[i] = e.getKey();
55  this.data[i + 1] = e.getValue();
56  i += 2;
57  }
58  }
59 
60  @Override
61  public int size() {
62  return this.data.length / 2;
63  }
64 
65  @Override
66  public boolean isEmpty() {
67  return this.data.length == 0;
68  }
69 
70  @Override
71  public boolean containsKey(Object key) {
72  for (int i = 0, n = this.data.length; i < n; i += 2) {
73  Object k = this.data[i];
74  if (Objects.equals(k, key)) {
75  return true;
76  }
77  }
78  return false;
79  }
80 
81  @Override
82  public boolean containsValue(Object value) {
83  for (int i = 1, n = this.data.length; i < n; i += 2) {
84  Object v = this.data[i];
85  if (Objects.equals(v, value)) {
86  return true;
87  }
88  }
89  return false;
90  }
91 
92  @Override
93  public V get(Object key) {
94  for (int i = 0, n = this.data.length; i < n; i += 2) {
95  Object k = this.data[i];
96  if (Objects.equals(k, key)) {
97  return (V) this.data[i + 1];
98  }
99  }
100  return null;
101  }
102 
103  public V put(K key, V value) {
104  for (int i = 0, n = this.data.length; i < n; i += 2) {
105  Object k = this.data[i];
106  if (Objects.equals(k, key)) {
107  V oldValue = (V) this.data[i + 1];
108  this.data[i + 1] = value;
109  return oldValue;
110  }
111  }
112  int oldLength = this.data.length;
113  this.data = Arrays.copyOf(this.data, oldLength + 2);
114  this.data[oldLength] = key;
115  this.data[oldLength + 1] = value;
116  return null;
117  }
118 
119  @Override
120  public V replace(K key, V value) {
121  for (int i = 0, n = this.data.length; i < n; i += 2) {
122  Object k = this.data[i];
123  if (Objects.equals(k, key)) {
124  V oldValue = (V) this.data[i + 1];
125  this.data[i + 1] = value;
126  return oldValue;
127  }
128  }
129  return null;
130  }
131 
132  @Override
133  public V remove(final Object key) {
134  for (int i = 0, n = this.data.length; i < n; i += 2) {
135  Object k = this.data[i];
136  if (Objects.equals(k, key)) {
137  V oldValue = (V) this.data[i + 1];
138  removeIndex(i);
139  return oldValue;
140  }
141  }
142  return null;
143  }
144 
145  @Override
146  public boolean remove(Object key, Object value) {
147  for (int i = 0, n = this.data.length; i < n; i += 2) {
148  Object k = this.data[i];
149  if (Objects.equals(k, key)) {
150  V v = (V) this.data[i + 1];
151  if (Objects.equals(v, value)) {
152  removeIndex(i);
153  return true;
154  }
155  }
156  }
157  return false;
158  }
159 
160  public boolean removeKey(final Object key) {
161  for (int i = 0, n = this.data.length; i < n; i += 2) {
162  Object k = this.data[i];
163  if (Objects.equals(k, key)) {
164  removeIndex(i);
165  return true;
166  }
167  }
168  return false;
169  }
170 
171  public boolean removeValue(final Object value) {
172  for (int i = 0, n = this.data.length; i < n; i += 2) {
173  Object v = this.data[i + 1];
174  if (Objects.equals(v, value)) {
175  removeIndex(i);
176  return true;
177  }
178  }
179  return false;
180  }
181 
182  private void removeIndex(int i) {
183  Object[] tmp = new Object[this.data.length - 2];
184  if (i > 0) {
185  System.arraycopy(this.data, 0, tmp, 0, i);
186  }
187  if (i + 2 < this.data.length) {
188  System.arraycopy(this.data, i + 2, tmp, i, this.data.length - 2 - i);
189  }
190  this.data = tmp;
191  }
192 
193  @Override
194  public void putAll(final Map<? extends K, ? extends V> m) {
195  m.forEach(this::put);
196  }
197 
198  @Override
199  public void clear() {
200  this.data = EMPTY;
201  }
202 
203  @Override
204  public Set<K> keySet() {
205  return new KeySetView<>(this);
206  }
207 
208  @Override
209  public Collection<V> values() {
210  return new ValuesView(this);
211  }
212 
213  @Override
214  public Set<java.util.Map.Entry<K, V>> entrySet() {
215  return new EntrySetView(this);
216  }
217 
218  private static class Entry<K, V> implements Map.Entry<K, V> {
219 
220  private final K k;
221  private final V v;
222 
223  public Entry(K k, V v) {
224  this.k = k;
225  this.v = v;
226  }
227 
228  @Override
229  public K getKey() {
230  return this.k;
231  }
232 
233  @Override
234  public V getValue() {
235  return this.v;
236  }
237 
238  @Override
239  public V setValue(final V value) {
240  throw new UnsupportedOperationException();
241  }
242 
243  @Override
244  public boolean equals(Object o) {
245  if (this == o) return true;
246  if (o == null || getClass() != o.getClass()) return false;
247  Entry<?, ?> entry = (Entry<?, ?>) o;
248  return Objects.equals(this.k, entry.k) &&
249  Objects.equals(this.v, entry.v);
250  }
251 
252  @Override
253  public int hashCode() {
254  return Objects.hash(this.k, this.v);
255  }
256  }
257 
258  private static class KeySetView<K, V> implements Set<K> {
259 
260  private final ArrayMap<K, V> map;
261 
263  this.map = map;
264  }
265 
266  @Override
267  public int size() {
268  return this.map.size();
269  }
270 
271  @Override
272  public boolean isEmpty() {
273  return this.map.isEmpty();
274  }
275 
276  @Override
277  public boolean contains(Object o) {
278  return this.map.containsKey(o);
279  }
280 
281  @Override
282  public Iterator<K> iterator() {
283  return new KeyIterator<K, V>(this.map);
284  }
285 
286  @Override
287  public Object[] toArray() {
288  Object[] data = this.map.data;
289  Object[] result = new Object[data.length / 2];
290  for (int i = 0; i < result.length; i++) {
291  result[i] = data[i * 2];
292  }
293  return result;
294  }
295 
296  @Override
297  public <T> T[] toArray(T[] a) {
298  Object[] data = this.map.data;
299  int resultLength = data.length / 2;
300  Object[] result = a;
301  if (result == null) {
302  result = new Object[resultLength];
303  } else if (result.length != resultLength) {
304  result = Arrays.copyOf(a, resultLength);
305  }
306  for (int i = 0; i < result.length; i++) {
307  result[i] = data[i * 2];
308  }
309  return (T[]) result;
310  }
311 
312  @Override
313  public boolean add(K k) {
314  throw new UnsupportedOperationException();
315  }
316 
317  @Override
318  public boolean remove(Object o) {
319  return this.map.removeKey(o);
320  }
321 
322  @Override
323  public boolean containsAll(Collection<?> c) {
324  for (Object o : c) {
325  if (!this.map.containsKey(o)) {
326  return false;
327  }
328  }
329  return true;
330  }
331 
332  @Override
333  public boolean addAll(Collection<? extends K> c) {
334  throw new UnsupportedOperationException();
335  }
336 
337  @Override
338  public boolean retainAll(Collection<?> c) {
339  boolean modified = false;
340  Object[] data = this.map.data;
341  for (int i = 0, n = data.length; i < n; i += 2) {
342  Object key = data[i];
343  if (!c.contains(key)) {
344  this.map.remove(key);
345  modified = true;
346  }
347  }
348  return modified;
349  }
350 
351  @Override
352  public boolean removeAll(Collection<?> c) {
353  boolean modified = false;
354  for (Object o : c) {
355  if (this.map.removeKey(o)) {
356  modified = true;
357  }
358  }
359  return modified;
360  }
361 
362  @Override
363  public void clear() {
364  this.map.clear();
365  }
366  }
367 
368  private static class KeyIterator<K, V> implements Iterator<K> {
369  private final ArrayMap<K, V> map;
370  private int nextIndex;
371 
373  this.map = map;
374  }
375 
376  @Override
377  public boolean hasNext() {
378  return this.map.data.length > this.nextIndex;
379  }
380 
381  @Override
382  public K next() {
383  if (hasNext()) {
384  K key = (K) this.map.data[this.nextIndex];
385  this.nextIndex += 2;
386  return key;
387  }
388  throw new NoSuchElementException();
389  }
390 
391  @Override
392  public void remove() {
393  this.nextIndex -= 2;
394  this.map.removeIndex(this.nextIndex);
395  }
396  }
397 
398  private static class ValuesView<K, V> implements Collection<V> {
399 
400  private final ArrayMap<K, V> map;
401 
403  this.map = map;
404  }
405 
406  @Override
407  public int size() {
408  return this.map.size();
409  }
410 
411  @Override
412  public boolean isEmpty() {
413  return this.map.isEmpty();
414  }
415 
416  @Override
417  public boolean contains(Object o) {
418  return this.map.containsValue(o);
419  }
420 
421  @Override
422  public Iterator<V> iterator() {
423  return new ValueIterator<>(this.map);
424  }
425 
426  @Override
427  public Object[] toArray() {
428  Object[] data = this.map.data;
429  Object[] result = new Object[data.length / 2];
430  for (int i = 0; i < result.length; i++) {
431  result[i] = data[i * 2 + 1];
432  }
433  return result;
434  }
435 
436  @Override
437  public <T> T[] toArray(T[] a) {
438  Object[] data = this.map.data;
439  int resultLength = data.length / 2;
440  Object[] result = a;
441  if (result == null) {
442  result = new Object[resultLength];
443  } else if (result.length != resultLength) {
444  result = Arrays.copyOf(a, resultLength);
445  }
446  for (int i = 0; i < result.length; i++) {
447  result[i] = data[i * 2 + 1];
448  }
449  return (T[]) result;
450  }
451 
452  @Override
453  public boolean add(V v) {
454  throw new UnsupportedOperationException();
455  }
456 
457  @Override
458  public boolean remove(Object o) {
459  return this.map.removeValue(o);
460  }
461 
462  @Override
463  public boolean containsAll(Collection<?> c) {
464  for (Object o : c) {
465  if (!this.map.containsValue(o)) {
466  return false;
467  }
468  }
469  return true;
470  }
471 
472  @Override
473  public boolean addAll(Collection<? extends V> c) {
474  throw new UnsupportedOperationException();
475  }
476 
477  @Override
478  public boolean removeAll(Collection<?> c) {
479  boolean modified = false;
480  for (Object o : c) {
481  if (this.map.removeValue(o)) {
482  modified = true;
483  }
484  }
485  return modified;
486  }
487 
488  @Override
489  public boolean retainAll(Collection<?> c) {
490  boolean modified = false;
491  Object[] data = this.map.data;
492  for (int i = 0, n = data.length; i < n; i += 2) {
493  Object value = data[i + 1];
494  if (!c.contains(value)) {
495  this.map.removeValue(value);
496  modified = true;
497  }
498  }
499  return modified;
500  }
501 
502  @Override
503  public void clear() {
504  this.map.clear();
505  }
506  }
507 
508  private static class ValueIterator<K, V> implements Iterator<V> {
509 
510  private final ArrayMap<K, V> map;
511  private int nextIndex;
512 
514  this.map = map;
515  }
516 
517  @Override
518  public boolean hasNext() {
519  return this.map.data.length > this.nextIndex;
520  }
521 
522  @Override
523  public V next() {
524  if (hasNext()) {
525  V value = (V) this.map.data[this.nextIndex + 1];
526  this.nextIndex += 2;
527  return value;
528  }
529  throw new NoSuchElementException();
530  }
531 
532  @Override
533  public void remove() {
534  this.nextIndex -= 2;
535  this.map.removeIndex(this.nextIndex);
536  }
537  }
538 
539  private static class EntrySetView<K, V> implements Set<java.util.Map.Entry<K, V>> {
540 
541  private final ArrayMap<K, V> map;
542 
544  this.map = map;
545  }
546 
547  @Override
548  public int size() {
549  return this.map.size();
550  }
551 
552  @Override
553  public boolean isEmpty() {
554  return this.map.isEmpty();
555  }
556 
557  @Override
558  public boolean contains(Object o) {
559  if (o instanceof Entry) {
560  Entry e = (Entry) o;
561  return Objects.equals(e.v, this.map.get(e.k));
562  }
563  return false;
564  }
565 
566  @Override
567  public Iterator<Map.Entry<K, V>> iterator() {
568  return new EntryIterator<>(this.map);
569  }
570 
571  @Override
572  public Object[] toArray() {
573  Object[] data = this.map.data;
574  Object[] result = new Object[data.length / 2];
575  for (int i = 0; i < result.length; i++) {
576  result[i] = new Entry<>(data[i * 2], data[i * 2 + 1]);
577  }
578  return result;
579  }
580 
581  @Override
582  public <T> T[] toArray(T[] a) {
583  Object[] data = this.map.data;
584  int resultLength = data.length / 2;
585  Object[] result = a;
586  if (result == null) {
587  result = new Object[resultLength];
588  } else if (result.length != resultLength) {
589  result = Arrays.copyOf(a, resultLength);
590  }
591  for (int i = 0; i < result.length; i++) {
592  result[i] = new Entry<>(data[i * 2], data[i * 2 + 1]);
593  }
594  return (T[]) result;
595  }
596 
597  @Override
598  public boolean add(Map.Entry<K, V> kvEntry) {
599  throw new UnsupportedOperationException();
600  }
601 
602  @Override
603  public boolean remove(Object o) {
604  if (o instanceof Entry) {
605  Entry e = (Entry) o;
606  return this.map.remove(e.k, e.v);
607  }
608  return false;
609  }
610 
611  @Override
612  public boolean containsAll(Collection<?> c) {
613  for (Object o : c) {
614  if (!this.contains(o)) {
615  return false;
616  }
617  }
618  return true;
619  }
620 
621  @Override
622  public boolean addAll(Collection<? extends Map.Entry<K, V>> c) {
623  throw new UnsupportedOperationException();
624  }
625 
626  @Override
627  public boolean retainAll(Collection<?> c) {
628  boolean modified = false;
629  Object[] data = this.map.data;
630  for (int i = 0, n = data.length; i < n; i += 2) {
631  Object key = data[i];
632  Object value = data[i + 1];
633  if (!c.contains(new Entry<>(key, value))) {
634  this.map.remove(key, value);
635  modified = true;
636  }
637  }
638  return modified;
639  }
640 
641  @Override
642  public boolean removeAll(Collection<?> c) {
643  boolean modified = false;
644  for (Object o : c) {
645  if (o instanceof Entry) {
646  Entry e = (Entry) o;
647  if (this.map.remove(e.k, e.v)) {
648  modified = true;
649  }
650  }
651  }
652  return modified;
653  }
654 
655  @Override
656  public void clear() {
657  this.map.clear();
658  }
659  }
660 
661  private static class EntryIterator<K, V> implements Iterator<java.util.Map.Entry<K, V>> {
662 
663  private final ArrayMap<K, V> map;
664  private int nextIndex;
665 
667  this.map = map;
668  }
669 
670  @Override
671  public boolean hasNext() {
672  return this.map.data.length > this.nextIndex;
673  }
674 
675  @Override
676  public java.util.Map.Entry<K, V> next() {
677  K key = (K) this.map.data[this.nextIndex];
678  V value = (V) this.map.data[this.nextIndex + 1];
679  this.nextIndex += 2;
680  return new Entry<>(key, value);
681  }
682 
683  }
684 
685 
686 }
final V v
Definition: ArrayMap.java:221
boolean isEmpty()
Definition: ArrayMap.java:553
Entry(K k, V v)
Definition: ArrayMap.java:223
Definition: ArrayMap.java:218
int hashCode()
Definition: ArrayMap.java:253
final ArrayMap< K, V > map
Definition: ArrayMap.java:663
boolean removeKey(final Object key)
Definition: ArrayMap.java:160
void putAll(final Map<? extends K, ? extends V > m)
Definition: ArrayMap.java:194
Iterator< Map.Entry< K, V > > iterator()
Definition: ArrayMap.java:567
boolean equals(Object o)
Definition: ArrayMap.java:244
V setValue(final V value)
Definition: ArrayMap.java:239
Definition: ArrayMap.java:539
boolean removeAll(Collection<?> c)
Definition: ArrayMap.java:642
boolean addAll(Collection<? extends Map.Entry< K, V >> c)
Definition: ArrayMap.java:622
void clear()
Definition: ArrayMap.java:656
int nextIndex
Definition: ArrayMap.java:664
K getKey()
Definition: ArrayMap.java:229
java.util.Map.Entry< K, V > next()
Definition: ArrayMap.java:676
boolean hasNext()
Definition: ArrayMap.java:671
boolean add(Map.Entry< K, V > kvEntry)
Definition: ArrayMap.java:598
final ArrayMap< K, V > map
Definition: ArrayMap.java:541
boolean retainAll(Collection<?> c)
Definition: ArrayMap.java:627
final K k
Definition: ArrayMap.java:220
boolean removeValue(final Object value)
Definition: ArrayMap.java:171
boolean containsAll(Collection<?> c)
Definition: ArrayMap.java:612
Definition: ArrayMap.java:661
Set< java.util.Map.Entry< K, V > > entrySet()
Definition: ArrayMap.java:214
boolean contains(Object o)
Definition: ArrayMap.java:558
V getValue()
Definition: ArrayMap.java:234
int size()
Definition: ArrayMap.java:548
Object [] toArray()
Definition: ArrayMap.java:572
boolean addAll(Collection<? extends V > c)
Definition: ArrayMap.java:473
boolean addAll(Collection<? extends K > c)
Definition: ArrayMap.java:333