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