View Javadoc
1   
2   
3   package eu.simuline.util;
4   
5   
6   import java.util.List;
7   import java.util.ArrayList;
8   import java.util.Set;
9   import java.util.SortedSet;
10  import java.util.AbstractSet;
11  import java.util.Collection;
12  import java.util.AbstractCollection;
13  import java.util.SortedMap;
14  import java.util.Map;
15  import java.util.Map.Entry;
16  import java.util.Comparator;
17  import java.util.Iterator;
18  import java.util.ListIterator;
19  import java.util.Objects;
20  
21  /**
22   * A {@link SortedMap} with ordering 
23   * given by the ordering by which the keys are added. 
24   * This is the {@link Map} corresponding with {@link ListSet}. 
25   * <p>
26   * Did not use {@link java.util.AbstractMap}, 
27   * e.g. because {@link #keySet()} shall return more than just a {@link Set}. 
28   *
29   * @param <K>
30   *    the class of keys for this map. 
31   * @param <V>
32   *    the class of values for this map. 
33   *
34   * @author <a href="mailto:ernst.reissner@simuline.eu">Ernst Reissner</a>
35   * @version 1.0
36   */
37  public final class ListMap<K, V> implements SortedMap<K, V> {
38  
39      /* -------------------------------------------------------------------- *
40       * Inner classes.                                                       *
41       * -------------------------------------------------------------------- */
42  
43      /**
44       * Class of entries of the encylosing map. 
45       * **** I wonder whether there is no generic implementation 
46       * for {@link java.util.Map.Entry}. 
47       */
48      private final class Entry implements Map.Entry<K, V> {
49  
50  	/* ------------------------------------------------------------------ *
51  	 * fields.                                                            *
52  	 * ------------------------------------------------------------------ */
53  
54  	/**
55  	 * The key of this entry. 
56  	 * The corresponding value is {@link #value}. 
57  	 */
58  	private final K key;
59  
60  	/**
61  	 * The value of this entry corresponding with the key {@link #key}. 
62  	 * Note that in contrast to the key, 
63  	 * the value of this entry may be changed 
64  	 * (through {@link #setValue(Object)}). 
65  	 */
66  	private V value;
67  
68  	/* ------------------------------------------------------------------ *
69  	 * constructors.                                                      *
70  	 * ------------------------------------------------------------------ */
71  
72  	/**
73  	 * Creates a new entry for the enclosing map 
74  	 * defined by the given <code>key</code> and <code>value</code>. 
75  	 */
76  	private Entry(K key, V value) {
77  	    this.key = key;
78  	    this.value = value;
79  	}
80  
81  	/* ------------------------------------------------------------------ *
82  	 * methods.                                                           *
83  	 * ------------------------------------------------------------------ */
84  
85  	/**
86  	 * Returns the {@link #key} of this entry. 
87  	 */
88  	public K getKey() {
89  	    return this.key;
90  	}
91  
92  	/**
93  	 * Returns the {@link #value} of this entry. 
94  	 */
95  	public V getValue() {
96  	    return this.value;
97  	}
98  
99  	/**
100 	 * Sets a new {@link #value} of this entry 
101 	 * and returns the original one. 
102 	 */
103 	public V setValue(V value) {
104 	    V oldValue = this.value;
105 	    this.value = value;
106 	    return oldValue;
107 	}
108 
109 	// fits with method equals 
110 	public int hashCode() {
111 	    return this.getKey().hashCode() + this.getValue().hashCode();
112 	}
113 
114 	// **** seems to be a bug in javadoc 
115 	/**
116 	 * Returns whether <code>obj</code> equals this entry, 
117 	 * i.e. whether <code>obj</code> 
118 	 * is an instance of {@link java.util.Map.Entry} 
119 	 * and both, its key and its value equals key and value of this entry. 
120 	 * Note that both, key and value may be <code>null</code>. 
121 	 */
122 	public boolean equals(Object obj) {
123 	    if (!(obj instanceof Map.Entry)) {
124 		return false;
125 	    }
126 
127 	    Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj;
128 	    return Objects.equals(this.getKey(),   other.getKey()) 
129 		&& Objects.equals(this.getValue(), other.getValue());
130 	}
131 
132     } // class Entry
133 
134     /**
135      * Represents the key set of the enclosing map 
136      * given by {@link ListMap#keySet()}. 
137      * <p>
138      * Like base class {@link AbstractSet}, 
139      * this class supports neither {@link Set#add(Object)} 
140      * nor {@link Set#addAll(Collection)}, 
141      * i.e. those methods throw an {@link UnsupportedOperationException}. 
142      * In contrast, this class supports methods 
143      * {@link Set#clear()}, 
144      * {@link Set#remove(Object)}, 
145      * {@link Set#removeAll(Collection)} and 
146      * {@link Set#retainAll(Collection)}. 
147      * The iterator returned by {@link #iterator()} 
148      * supports {@link Iterator#remove()}. 
149      *
150      * @see ListMap#keysSet
151      */
152     private class Keys extends AbstractSet<K> implements SortedSet<K> {
153 
154 	/* ------------------------------------------------------------------ *
155 	 * methods implementing Set based on AbstractSet.                     *
156 	 * ------------------------------------------------------------------ */
157 
158 	/**
159 	 * Returns actually an instance of {@link ListMap.KeysIterator}. 
160 	 */
161         public Iterator<K> iterator() {
162             return new KeysIterator();
163         }
164 
165 	/**
166 	 * Returns actually the size of the enclosing {@link ListMap} 
167 	 * delegating to {@link ListMap#size()}. 
168 	 */
169 	public int size() {
170 	    return ListMap.this.size();
171         }
172 
173 	/**
174 	 * Returns actually whether <code>obj</code> 
175 	 * is a key of the enclosing {@link ListMap} 
176 	 * delegating to {@link ListMap#containsKey(Object)}. 
177 	 */
178         public boolean contains(Object obj) {
179 	    return ListMap.this.containsKey(obj);
180         }
181 
182 	/**
183 	 * Interpretes <code>obj</code> as key 
184 	 * of the enclosing {@link ListMap} 
185 	 * and removes the according key-value pair if present. 
186 	 * Returns whether the according key-value pair was present 
187 	 * when invoking this method using 
188 	 * {@link ListMap#removeIdx(int)}. 
189 	 */
190          public boolean remove(Object obj) {
191 	    int idx = ListMap.this.keys.getList().indexOf(obj);
192 	    return ListMap.this.removeIdx(idx);
193         }
194 
195 	/**
196 	 * Clears actually the enclosing {@link ListMap} 
197 	 * delegating to {@link ListMap#clear()}. 
198 	 */
199         public void clear() {
200             ListMap.this.clear();
201 	}
202 
203 	/* ------------------------------------------------------------------ *
204 	 * methods implementing SortedSet.                                    *
205 	 * ------------------------------------------------------------------ */
206 
207 	public Comparator<? super K> comparator() {
208 	    return ListMap.this.comparator();
209 	}
210 
211 	public K first() {
212 	    return ListMap.this.keys.first();
213 	}
214 
215 	public K last() {
216 	    return ListMap.this.keys.last();
217 	}
218 
219 	public SortedSet<K> subSet(K fromElement, K toElement) {
220 	    return ListMap.this.subMap(fromElement, toElement).keySet();
221 	}
222 
223 	public SortedSet<K> headSet(K toElement) {
224 	    return ListMap.this.headMap(toElement).keySet();
225 	}
226 
227 	public SortedSet<K> tailSet(K fromElement) {
228 	    return ListMap.this.tailMap(fromElement).keySet();
229 	}
230 
231     } // class Keys 
232 
233     /**
234      * Class of iterator of class  {@link ListMap.Keys}. 
235      *
236      * @see ListMap.Keys#iterator()
237      */
238     private class KeysIterator extends XIterator implements Iterator<K> {
239     	public K next() {
240             return this.lIter.next();
241         }
242     } //  class KeysIterator
243 
244 
245     /**
246      * Represents the set of entries of the enclosing map 
247      * given by {@link ListMap#entrySet()}. 
248      * <p>
249      * Like base class {@link AbstractSet}, 
250      * this class supports neither {@link Set#add(Object)} 
251      * nor {@link Set#addAll(Collection)}, 
252      * i.e. those methods throw an {@link UnsupportedOperationException}. 
253      * In contrast, this class supports methods 
254      * {@link Set#clear()}, 
255      * {@link Set#remove(Object)}, 
256      * {@link Set#removeAll(Collection)} and 
257      * {@link Set#retainAll(Collection)}. 
258      * The iterator returned by {@link #iterator()} 
259      * supports {@link Iterator#remove()}. 
260      *
261      * @see ListMap#entrySet
262      */
263     private class Entries
264 	extends  AbstractSet<Map.Entry<K, V>> 
265 	implements SortedSet<Map.Entry<K, V>> {
266 
267 	/* ------------------------------------------------------------------ *
268 	 * methods implementing Set based on AbstractSet.                     *
269 	 * ------------------------------------------------------------------ */
270 
271 	/**
272 	 * Returns actually an instance of {@link ListMap.EntriesIterator}. 
273 	 */
274         public Iterator<Map.Entry<K, V>> iterator() {
275             return new EntriesIterator();
276 	}
277 
278 	/**
279 	 * Returns actually the size of the enclosing {@link ListMap} 
280 	 * delegating to {@link ListMap#size()}. 
281 	 */
282         public int size() {
283 	    return ListMap.this.size();
284         }
285 
286 	/**
287 	 * Assumes that <code>obj</code> is a {@link java.util.Map.Entry} 
288 	 * and returns its key. 
289 	 *
290 	 * @throws NullPointerException 
291 	 *    if <code>obj</code> is <code>null</code>. 
292 	 * @throws ClassCastException 
293 	 *    if <code>obj</code> is neither <code>null</code> 
294 	 *    nor an instance of {@link java.util.Map.Entry}. 
295 	 */
296 	private Object getKey(Object obj) {
297 	    Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
298 	    return entry.getKey();
299 	}
300 
301 	/**
302 	 * Returns actually whether <code>obj</code> 
303 	 * is an instance of {@link java.util.Map.Entry} 
304 	 * with a key contained in the enclosing {@link ListMap} 
305 	 * delegating to {@link ListMap#containsKey(Object)}. 
306 	 */
307         public boolean contains(Object obj) {
308 	    if (!(obj instanceof Map.Entry)) {
309 		return false;
310 	    }
311 	    return ListMap.this.containsKey(getKey(obj));
312         }
313 
314 	/**
315 	 * Removes <code>obj</code> from the entry set if present 
316 	 * and returns whether it was present. 
317 	 * Effectively checks whether <code>obj</code> 
318 	 * is an instance of {@link java.util.Map.Entry}. 
319 	 * If not returns <code>false</code>. 
320 	 * If it is an instance of {@link java.util.Map.Entry}
321 	 * removes the according key-value pair 
322 	 * from the enclosing {@link ListMap} if present. 
323 	 * Returns whether <code>obj</code>'s key was present 
324 	 * when invoking this method. 
325 	 * This is done 
326 	 * invoking {@link ListMap.Keys#remove(Object)}. 
327 	 */
328         public boolean remove(Object obj) {
329 	    if (!(obj instanceof Map.Entry)) {
330 		return false;
331 	    }
332 	    Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
333 	    entry.getClass().getTypeParameters();
334 	    return ListMap.this.keysSet.remove(getKey(entry));
335         }
336 
337 	/**
338 	 * Clears actually the enclosing {@link ListMap} 
339 	 * delegating to {@link ListMap#clear()}. 
340 	 */
341         public void clear() {
342 	    ListMap.this.clear();
343  	}
344 
345 	/* ------------------------------------------------------------------ *
346 	 * methods implementing SortedSet.                                    *
347 	 * ------------------------------------------------------------------ */
348 
349 	public Comparator<? super Map.Entry<K, V>> comparator() {
350 	    return new  Comparator<Map.Entry<K, V>>() {
351 		public int compare(Map.Entry<K, V> entry1, 
352 				   Map.Entry<K, V> entry2) {
353 		    return ListMap.this.comparator()
354 			.compare(entry1.getKey(), entry2.getKey());
355 		}
356 	    };
357 	}
358 
359 	private Map.Entry<K, V> key2entry(K key) {
360 	    return new ListMap<K, V>.Entry(key, get(key));
361 	}
362 
363 	public Map.Entry<K, V> first() {
364 	    return key2entry(ListMap.this.keys.first());
365 	}
366 
367 	public Map.Entry<K, V> last() {
368 	    return key2entry(ListMap.this.keys.last());
369 	}
370 
371 	public SortedSet<Map.Entry<K, V>> subSet(Map.Entry<K, V> fromElement, 
372 					         Map.Entry<K, V>   toElement) {
373 	    return ListMap.this.subMap(fromElement.getKey(),
374 				       toElement  .getKey()).entrySet();
375 	}
376 
377 	public SortedSet<Map.Entry<K, V>> headSet(Map.Entry<K, V>  toElement) {
378 	    return ListMap.this.headMap(toElement  .getKey()).entrySet();
379 	}
380 
381 	public SortedSet<Map.Entry<K, V>> tailSet(Map.Entry<K, V> fromElement) {
382 	    return ListMap.this.tailMap(fromElement.getKey()).entrySet();
383 	}
384 
385     } // class Entries 
386 
387     /**
388      * Class of iterator of class  {@link ListMap.Entries}. 
389      *
390      * @see ListMap.Entries#iterator()
391      */
392     private class EntriesIterator extends XIterator 
393 	implements Iterator<Map.Entry<K, V>> {
394 
395     	public Map.Entry<K, V> next() {
396 	    int idx = this.lIter.nextIndex();
397 	    return new Entry(this.lIter.next(), 
398 			     ListMap.this.values.get(idx));
399         }
400     } //  class EntriesIterator
401 
402     /**
403      * Represents the values collection of the enclosing map 
404      * given by {@link ListMap#values()}. 
405      * <p>
406      * Like base class {@link AbstractCollection}, 
407      * this class supports neither {@link Collection#add(Object)} 
408      * nor {@link Collection#addAll(Collection)}, 
409      * i.e. those methods throw an {@link UnsupportedOperationException}. 
410      * In contrast, this class supports methods 
411      * {@link Set#clear()}, 
412      * {@link Collection#remove(Object)}, 
413      * {@link Collection#removeAll(Collection)} and 
414      * {@link Collection#retainAll(Collection)}. 
415      * The iterator returned by {@link #iterator()} 
416      * supports @link Iterator#remove()}. 
417      *
418      * @see ListMap#valuesColl
419      */
420     private class Values extends AbstractCollection<V> {
421 
422 	/**
423 	 * Returns actually an instance of {@link ListMap.ValuesIterator}. 
424 	 */
425         public Iterator<V> iterator() {
426             return new ValuesIterator();
427         }
428 
429 	/**
430 	 * Returns actually the size of the enclosing {@link ListMap} 
431 	 * delegating to {@link ListMap#size()}. 
432 	 */
433         public int size() {
434 	    return ListMap.this.size();
435         }
436 
437 	/**
438 	 * Returns actually whether <code>obj</code> 
439 	 * is a value of the enclosing {@link ListMap} 
440 	 * delegating to {@link ListMap#containsValue(Object)}. 
441 	 */
442         public boolean contains(Object obj) {
443 	    return ListMap.this.containsValue(obj);
444 	}
445 
446 	/**
447 	 * Interpretes <code>obj</code> as value 
448 	 * of the enclosing {@link ListMap} 
449 	 * and removes the first according key-value pair if present. 
450 	 * Returns whether the according key-value pair was present 
451 	 * when invoking this method invoking using 
452 	 * {@link ListMap#removeIdx(int)}. 
453 	 */
454         public boolean remove(Object obj) {
455 	    int idx = ListMap.this.values.indexOf(obj);
456 	    return ListMap.this.removeIdx(idx);
457         }
458 
459 	/**
460 	 * Clears actually the enclosing {@link ListMap} 
461 	 * delegating to {@link ListMap#clear()}. 
462 	 */
463           public void clear() {
464 	    ListMap.this.clear();
465 	}
466 
467     } // class Values 
468 
469     /**
470      * Class of iterator of class  {@link ListMap.Values}. 
471      *
472      * @see ListMap.Values#iterator()
473      */
474     @edu.umd.cs.findbugs.annotations.SuppressWarnings
475 	(value = "RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT", 
476 	 justification = "bug in findbugs")
477     private class ValuesIterator extends XIterator implements Iterator<V> {
478   	public V next() {
479 	    int idx = this.lIter.nextIndex();
480             this.lIter.next(); // has side effect! 
481 	    return ListMap.this.values.get(idx);
482         }
483     } //  class ValuesIterator
484 
485     /**
486      * Common superclass of iterators on key set, 
487      * value collection and entries set 
488      * providing all methods but {@link Iterator#next()}. 
489      * Implementation is based on a {@link ListIterator}. 
490      */
491     private abstract class XIterator {
492 
493 	/* ------------------------------------------------------------------ *
494 	 * fields.                                                            *
495 	 * ------------------------------------------------------------------ */
496 
497 	/**
498 	 * An iterator over the list view of the key set 
499 	 * of the enclosing {@link ListMap}. 
500 	 *
501 	 * @see ListMap#keys
502 	 * @see ListSet#getList()
503 	 */
504 	@SuppressWarnings("checkstyle:visibilitymodifier")
505 	protected final ListIterator<K> lIter;
506 
507 	/* ------------------------------------------------------------------ *
508 	 * constructors.                                                      *
509 	 * ------------------------------------------------------------------ */
510 
511 	/**
512 	 * Creates a pre-iterator. 
513 	 *
514 	 * @see ListMap#keys
515 	 * @see ListSet#getList()
516 	 */
517 	XIterator() {
518 	    this.lIter = ListMap.this.keys.getList().listIterator();
519 	}
520 
521 	/* ------------------------------------------------------------------ *
522 	 * methods.                                                           *
523 	 * ------------------------------------------------------------------ */
524 
525 	/**
526 	 * Returns whether the iterators based on this class 
527 	 * has a next value. 
528 	 *
529 	 * @see Iterator#hasNext()
530 	 */
531     	public boolean hasNext() {
532             return this.lIter.hasNext();
533         }
534     	//public abstract X next();
535 
536 	/**
537 	 * Removes from the underlying collection the last element returned 
538 	 * by the iterator based on this class.	
539 	 *
540 	 * @see Iterator#remove()
541 	 */
542     	public void remove() {
543 	    // get the index of the element returned by next() last 
544 	    int idxPrev = this.lIter.previousIndex();
545 	    if (idxPrev == -1) {
546 		// never called next() 
547 		throw new IllegalStateException();
548 	    }
549 	    ListMap.this.removeIdx(idxPrev);
550         }
551     } //  class XIterator
552 
553     /* -------------------------------------------------------------------- *
554      * fields.                                                              *
555      * -------------------------------------------------------------------- */
556 
557     /**
558      * The set of keys of this <code>ListMap</code>. 
559      */
560     private final ListSet<K> keys;
561 
562     /**
563      * The values of this map. 
564      * The according keys are in {@link #keys}. 
565      */
566     private final List<V> values;
567 
568     /**
569      * The collection of values of this map returned by {@link #values()}. 
570      * Note that each <code>ListMap</code> has a single values collection. 
571      */
572     private final Collection<V> valuesColl;
573 
574     /**
575      * The set of keys of this map returned by {@link #keySet()}. 
576      * Note that each <code>ListMap</code> has a single key set. 
577      */
578     private final SortedSet<K> keysSet;
579 
580     /**
581      * The set of entries of this map returned by {@link #entrySet()}. 
582      * Note that each <code>ListMap</code> has a single entry set. 
583      */
584     private final SortedSet<Map.Entry<K, V>> entrySet;
585 
586     /* -------------------------------------------------------------------- *
587      * constructors and auxiliary methods.                                  *
588      * -------------------------------------------------------------------- */
589 
590     /**
591      * Creates an empty list map with key set 'ordered as added' 
592      * as described by {@link ListSet#sortedAsAdded()}. 
593      */
594     public ListMap() {
595 	this(ListSet.sortedAsAdded(), new ArrayList<V>());
596     }
597 
598     /**
599      * Creates an list map with the same key-value pairs as <code>map</code> 
600      * and with ordering 'as added'. 
601      * If no additional keys are added, this reflects the ordering 
602      * given by iterating through the key set of <code>map</code>. 
603      *
604      * @see #map2keys(Map)
605      * @see #map2values(Map)
606      */
607     public ListMap(Map<K, V> map) {
608 	this(map2keys(map), map2values(map));
609     }
610 
611     /**
612      * Returns the key set of <code>map</code> as a <code>ListSet</code> 
613      * with ordering 'ordered as added' 
614      * as given by {@link ListSet#sortedAsAdded()}. 
615      * This ordering reflects the ordering 
616      * given by the iteration on the key set of <code>map</code>. 
617      */
618     private static <K, V> ListSet<K> map2keys(Map<K, V> map) {
619 	ListSet<K> res = ListSet.sortedAsAdded();
620 	res.addAll(map.keySet());
621 	return res;
622     }
623 
624     /**
625      * Returns the value collection of <code>map</code> as a <code>List</code> 
626      * with ordering 
627      * given by the iteration on the key set of <code>map</code>. 
628      * Note that there is no documentation **** 
629      * that this ordering is the same as the one 
630      * of the value collection {@link Map#values() map#values()}. **** 
631      */
632     private static <K, V> List<V> map2values(Map<K, V> map) {
633 	List<V> res = new ArrayList<V>();
634 	// **** using entrySet() would be more elegant, 
635 	// but seems not to guarantee an ordering of iteration. 
636 	for (K key : map.keySet()) {
637 	    res.add(map.get(key));
638 	}
639 	return res;
640     }
641 
642     /**
643      * Creates a list map defined by the given keys and values 
644      * <code>keys</code> and <code>values</code>. 
645      * A key and a value correspond iff their index coincides. 
646      * Thus <code>keys</code> and <code>values</code> must have the same size. 
647      * Note that the entries of <code>keys</code> differ pairwise, 
648      * whereas this is not necessary for <code>values</code>. 
649      *
650      * @param keys
651      *    the set of keys as a {@link ListSet}. 
652      * @param values
653      *    the collection of according values as a {@link List} 
654      *    with the same size as <code>keys</code>. 
655      * @throws IllegalArgumentException
656      *    if <code>keys</code> and <code>values</code> differ in size. 
657      */
658     private ListMap(ListSet<K> keys, List<V> values) {
659 	if (keys.size() != values.size()) {
660 	    throw new IllegalArgumentException
661 		("Collection of keys and values must have same size. ");
662 	}
663 
664 	this.keys       = keys;
665 	this.values     = values;
666 	this.valuesColl = new Values();
667 	this.keysSet    = new Keys();
668 	this.entrySet   = new Entries();
669     }
670 
671     /* -------------------------------------------------------------------- *
672      * Methods.                                                             *
673      * -------------------------------------------------------------------- */
674 
675     public void clear() {
676 	this.keys  .clear();
677 	this.values.clear();
678     }
679 
680     public boolean containsKey(Object key) {
681 	return this.keys.contains(key);
682     }
683 
684     public boolean containsValue(Object val) {
685 	return this.values.contains(val);
686     }
687 
688     public SortedSet<Map.Entry<K, V>> entrySet() {
689 	return this.entrySet;
690     }
691 
692     public V get(Object key) {
693 	int idx = this.keys.getList().indexOf(key);
694 	if (idx == -1) {
695 	    return null;
696 	}
697 	assert idx >= 0 && idx < size();
698 	return this.values.get(idx);
699     }
700 
701     public boolean isEmpty() {
702 	assert this.keys.isEmpty() == this.values.isEmpty();
703 	return this.keys.isEmpty();
704     }
705 
706     public SortedSet<K> keySet() {
707 	return this.keysSet;
708     }
709 
710     public V put(K key, V value) {
711 	int idx = this.keys.getList().indexOf(key);
712 	if (idx == -1) {
713 	    // Here, key is to be added 
714 	    this.keys.getList().add(key);
715 	    this.values.add(value);
716 	    return null;
717 	}
718 	assert idx >= 0 && idx < size();
719 
720 	return this.values.set(idx, value);
721     }
722 
723     public void putAll(Map<? extends K, ? extends V> other) {
724 	Iterator<? extends K> iter = other.keySet().iterator();
725 	K key;
726 	while (iter.hasNext()) {
727 	    key = iter.next();
728 	    this.put(key, other.get(key));
729 	}
730     }
731 
732     public V remove(Object key) {
733 	int idx = this.keys.getList().indexOf(key);
734 	if (idx == -1) {
735 	    return null;
736 	}
737 	assert idx >= 0 && idx < size();
738 	V res = this.values.get(idx);
739 	this.keys.getList().remove(idx);
740 	this.values.remove(idx);
741 	return res;
742     }
743 
744     private boolean removeIdx(int idx) {
745 	if (idx == -1) {
746 	    return false;
747 	}
748 	assert idx >= 0 && idx < size();
749 	this.keys.getList().remove(idx);
750 	this.values.remove(idx);
751 	return true;
752     }
753 
754     public int size() {
755 	return this.keys.size();
756     }
757 
758     public Comparator<? super K> comparator() {
759 	return this.keys.comparator();
760     }
761 
762     public Collection<V> values() {
763 	return this.valuesColl;
764     }
765 
766     // also throws correct exception 
767     public K firstKey() {
768 	return keySet().first();
769     }
770 
771    // also throws correct exception 
772     public K lastKey() {
773 	return keySet().last();
774     }
775 
776     // better removed because easy to mix up with other methods 
777     // offering just a view, not a copy of part of this map 
778     // public Map<K,V> subMap(Set<K> someKeys) {
779     // 	V val;
780     // 	ListMap<K, V> res = new ListMap<K, V>();
781     // 	for (K key : someKeys) {
782     // 	    val = get(key);
783     // 	    res.put(key, val);
784     // 	}
785     // 	return res;
786     // }
787 
788     public ListMap<K, V> headMap(K toKey) {
789 	return subMap(0, this.keys.obj2idx(toKey));
790     }
791 
792     public ListMap<K, V> tailMap(K fromKey) {
793  	return subMap(this.keys.obj2idx(fromKey), size());
794     }
795 
796 
797     @SuppressWarnings("checkstyle:genericwhitespace")
798     ListMap<K, V> subMap(int fromIdx, int toIdx) {
799 	ListSet<K> subKeys   = this.keys  .subSetIdx(fromIdx, toIdx);
800 	List   <V> subValues = this.values.subList  (fromIdx, toIdx);
801 
802 	return new ListMap<K, V>(subKeys, subValues);
803     }
804 
805     public ListMap<K, V> subMap(K fromKey, K toKey) {
806 	return subMap(this.keys.obj2idx(fromKey), this.keys.obj2idx(toKey));
807     }
808 
809     public boolean equals(Object obj) {
810 	if (!(obj instanceof Map)) {
811 	    return false;
812 	}
813 
814 	Map<?, ?> other = (Map<?, ?>) obj;
815 	return this.entrySet().equals(other.entrySet());
816     }
817 
818     public int hashCode() {
819 	return this.entrySet().hashCode();
820     }
821 
822     public String toString() {
823 	StringBuffer result = new StringBuffer();
824 	result.append("<ListMap>\n");
825 	for (int i = 0; i < size(); i++) {
826 	    result.append("[" + this.keys.getList().get(i) 
827 			  + " => " + this.values.get(i) + "]\n");
828 	}
829 	result.append("</ListMap>\n");
830 
831 	return result.toString();
832     }
833 
834     public static void main(String[] args) {
835 	List<Integer> list = new ArrayList<Integer>();
836 	//list.add(0);
837 	list.iterator().remove();
838     }
839 }