/* * Concept profile generation tool suite * Copyright (C) 2015 Biosemantics Group, Erasmus University Medical Center, * Rotterdam, The Netherlands * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> */ package org.erasmusmc.collections; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; public class SortedListMap<K, V> implements Serializable, Map<K, V> { private static final long serialVersionUID = -2937148184646196003L; protected ArrayList<MapEntry<K,V>> mapEntries = new ArrayList<MapEntry<K,V>>(); protected Comparator<K> comparator; public class MapEntry<K2,V2> implements java.util.Map.Entry<K,V> { protected K key; protected V value; public K getKey() { return key; } public V getValue() { return value; } public MapEntry(K key, V value) { this.key = key; this.value = value; } public V setValue(V newvalue) { V old = this.value; this.value=newvalue; return old; } } public SortedListMap(Comparator<K> comparator) { this.comparator = comparator; } /** * special function for efficiency if you add an entry to end by bypassing * binarysearch */ public void addEntry(K key, V value) { mapEntries.add(new MapEntry<K,V>(key, value)); } public SortedListSet<K> getKeySet() { SortedListSet<K> result = new SortedListSet<K>(comparator); List<K> inbetween = new ArrayList<K>(); Iterator<K> iterator = keyIterator(); while (iterator.hasNext()) { inbetween.add(iterator.next()); } result.setSortedList(inbetween); return result; } public Iterator<V> iterator() { return new Iterator<V>() { int index = 0; public boolean hasNext() { return index < mapEntries.size(); } public V next() { return mapEntries.get(index++).value; } public void remove() { } }; } public Integer getIndexForKey(K key) { return binarySearch(key); } public Integer guidedGetIndexForKey(K key, int low, int high) { return binarySearch(key, low, high); } public V put(K key, V element) { int index = binarySearch(key); V result = null; if (index < mapEntries.size()) { MapEntry<K,V> mapEntry = mapEntries.get(index); if (comparator.compare(key, mapEntry.key) == 0) { result = mapEntry.value; mapEntry.value = element; } else mapEntries.add(index, new MapEntry<K,V>(key, element)); } else mapEntries.add(index, new MapEntry<K,V>(key, element)); return result; } public boolean containsKey(Object key) { V v = get(key); if (v == null) { return false; } else { return true; } } public void putAll(SortedListMap<K, ? extends V> map) { Iterator<? extends K> iterator = map.keyIterator(); while (iterator.hasNext()) { K k = iterator.next(); put(k, map.get(k)); } } public V guidedGet(K key, int low, int high) { int index = binarySearch(key, low, high); if (index < mapEntries.size()) { MapEntry<K,V> mapEntry = mapEntries.get(index); if (comparator.compare(key, mapEntry.key) == 0) return mapEntry.value; } return null; } @SuppressWarnings("unchecked") public V get(Object key) { try { K castKey = (K) key; return guidedGet(castKey, 0, mapEntries.size()); } catch (ClassCastException e) { // we do nothing now, just return null return null; } } public K getKey(int index) { return mapEntries.get(index).key; } public V getValue(int index) { return mapEntries.get(index).value; } @SuppressWarnings("unchecked") public V remove(Object key) { try { K castKey = (K) key; int index = binarySearch(castKey); if (index < mapEntries.size()) { MapEntry<K,V> mapEntry = mapEntries.get(index); if (comparator.compare(castKey, mapEntry.key) == 0) { mapEntries.remove(index); return mapEntry.value; } } return null; } catch (ClassCastException e) { // we do nothing now, just return null return null; } } protected int binarySearch(K key, int low, int high) { int middle; while (low < high) { middle = (low + high) / 2; if (comparator.compare(key, mapEntries.get(middle).key) > 0) low = middle + 1; else high = middle; } return low; } protected int binarySearch(K key) { int low = 0, high = mapEntries.size(); return binarySearch(key, low, high); } public void pack() { mapEntries.trimToSize(); } public int size() { return mapEntries.size(); } public void clear() { mapEntries.clear(); } public Iterator<K> keyIterator() { return new KeyIterator(); } public Iterator<MapEntry<K,V>> entryIterator() { return mapEntries.iterator(); } private class KeyIterator implements Iterator<K>, Serializable { private static final long serialVersionUID = -2585856627438009997L; protected Iterator<MapEntry<K, V>> iterator = mapEntries.iterator(); public boolean hasNext() { return iterator.hasNext(); } public K next() { return iterator.next().key; } public void remove() { } } public boolean containsValue(Object value) { boolean control = false; int i=0; while (i<mapEntries.size()&&!control){ if(mapEntries.get(i++).value.equals(value)){ control = true; } } return control; } public Set<java.util.Map.Entry<K, V>> entrySet() { Set<java.util.Map.Entry<K, V>> result =new HashSet<java.util.Map.Entry<K, V>>(); result.addAll(mapEntries); return result; } public boolean isEmpty() { if (size()==0){ return true; } return false; } public void putAll(Map<? extends K, ? extends V> m) { for (Entry<? extends K, ? extends V> entry: m.entrySet()) { put(entry.getKey(), entry.getValue()); } } public Collection<V> values() { Iterator<MapEntry<K,V>> it = entryIterator(); List<V> val = new ArrayList<V>(); while (it.hasNext()){ val.add(it.next().value); } return val; } public Set<K> keySet() { return getKeySet(); }; }