/*
* 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.Iterator;
public class SortedIntList2IntMap implements Serializable {
private static final long serialVersionUID = -285748620620480541L;
private IntList keys;
private IntList values;
public SortedIntList2IntMap() {
keys = new IntList();
values = new IntList();
}
public SortedIntList2IntMap(int initialCapacity) {
keys = new IntList(initialCapacity);
values = new IntList(initialCapacity);
}
/**
* special function for efficiency if you add an entry to end by bypassing
* binarysearch
*/
public void addEntry(int key, int value) {
keys.add(key);
values.add(value);
}
public int getIndexForKey(int key) {
return binarySearch(key);
}
public Integer guidedGetIndexForKey(int key, int low, int high) {
return binarySearch(key, low, high);
}
public void put(int key, int element) {
int index = binarySearch(key);
if (index < keys.size()) {
if (key == keys.getInt(index))
values.set(index, element);
else {
keys.add(index, key);
values.add(index, element);
}
}
else {
keys.add(index, key);
values.add(index, element);
}
}
/**
* Adds the increment to the value in the map. If the key and value do not yet exist they are created,
* and the value is set to the increment
* @param key
* @param increment
*/
public void add(int key, int increment){
int index = binarySearch(key);
if (index < keys.size()) {
if (key == keys.getInt(index))
values.set(index, values.get(index) + increment);
else {
keys.add(index, key);
values.add(index, increment);
}
}
else {
keys.add(index, key);
values.add(index, increment);
}
}
public boolean containsKey(int key) {
Integer v = get(key);
if (v == null) {
return false;
}
else {
return true;
}
}
public void putAll(SortedIntList2IntMap map) {
Iterator<MapEntry> iterator = map.entryIterator();
while (iterator.hasNext()) {
MapEntry k = iterator.next();
put(k.key, k.value);
}
}
public Integer guidedGet(int key, int low, int high) {
int index = binarySearch(key, low, high);
if (index < keys.size()) {
if (key == keys.getInt(index))
return values.getInt(index);
}
return null;
}
public Integer get(int key) {
return guidedGet(key, 0, keys.size());
}
public int getKey(int index) {
return keys.getInt(index);
}
public int getValue(int index) {
return values.getInt(index);
}
public Integer remove(int key) {
int index = binarySearch(key);
if (index < keys.size()) {
if (keys.getInt(index) == key) {
keys.remove(index);
int value = values.getInt(index);
values.remove(index);
return value;
}
}
return null;
}
protected int binarySearch(int key, int low, int high) {
int middle;
while (low < high) {
middle = (low + high) / 2;
if (key > keys.getInt(middle))
low = middle + 1;
else
high = middle;
}
return low;
}
protected int binarySearch(int key) {
int low = 0, high = keys.size();
return binarySearch(key, low, high);
}
public void pack() {
keys.trimToSize();
values.trimToSize();
}
public int size() {
return keys.size();
}
public void clear() {
keys.clear();
values.clear();
}
public Iterator<Integer> keyIterator() {
return new KeyIterator();
}
public Iterator<MapEntry> entryIterator() {
return new EntryIterator();
}
private class KeyIterator implements Iterator<Integer> {
private int currentIndex = 0;
public boolean hasNext() {
return currentIndex < keys.size();
}
public Integer next() {
return keys.getInt(currentIndex++);
}
public void remove() {
}
};
public class MapEntry {
int key;
int value;
public MapEntry(int key, int value) {
this.key = key;
this.value = value;
}
public int getKey() {
return key;
}
public int getValue() {
return value;
}
}
public MapCursor<Integer, Integer> getEntryCursor() {
return new EntryCursor();
}
protected class EntryCursor implements MapCursor<Integer, Integer> {
private int index = 0;
private boolean removeCheck;
public boolean isValid() {
return index < keys.size() && !removeCheck;
}
public Integer key() {
if (isValid())
return keys.getInt(index);
else
return null;
}
public void next() {
if (removeCheck)
removeCheck=false;
index++;
}
public void setValue(Integer value) {
if (isValid())
values.set(index, value);
}
public Integer value() {
if (isValid())
return values.getInt(index);
else
return null;
}
public Integer remove() {
keys.remove(index);
Integer returnValue =values.remove(index);
index--;
removeCheck=true;
return returnValue;
}
}
protected class EntryIterator implements Iterator<MapEntry> {
private int index = 0;
public boolean hasNext() {
return index < keys.size();
}
public MapEntry next() {
return new MapEntry(keys.getInt(index), values.getInt(index++));
}
public void remove() {
}
}
}