/*
* 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 SortedIntList2FloatMap implements Serializable {
private static final long serialVersionUID = -2857486206204805801L;
private IntList keys;
private FloatList values;
// make supersleak cursor! for high speed reading
public SortedIntList2FloatMap() {
keys = new IntList();
values = new FloatList();
}
public SortedIntList2FloatMap(int initialCapacity) {
keys = new IntList(initialCapacity);
values = new FloatList(initialCapacity);
}
public SortedIntListSet getKeySet() {
return new SortedIntListSet(keys);
}
public IntList keys(){
return keys;
}
public FloatList values(){
return values;
}
/**
* special function for efficiency if you add an entry to end by bypassing
* binarysearch
*/
public void addEntry(int key, float 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, float 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);
}
}
public boolean containsKey(int key) {
float v = get(key);
if (Float.isNaN(v)) {
return false;
}
else {
return true;
}
}
public void putAll(SortedIntList2FloatMap map) {
Iterator<Integer> iterator = map.keyIterator();
while (iterator.hasNext()) {
int k = iterator.next();
put(k, map.get(k));
}
}
public float guidedGet(int key, int low, int high) {
int index = binarySearch(key, low, high);
if (index < keys.size()) {
if (key == keys.getInt(index))
return values.get(index);
}
return Float.NaN;
}
public float get(int key) {
return guidedGet(key, 0, keys.size());
}
public int getKey(int index) {
return keys.getInt(index);
}
public float getValue(int index) {
return values.get(index);
}
public float remove(int key) {
int index = binarySearch(key);
if (index < keys.size()) {
if (keys.getInt(index) == key) {
keys.remove(index);
float value = values.get(index);
values.remove(index);
return value;
}
}
return Float.NaN;
}
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;
float value;
public MapEntry(int key, float value) {
this.key = key;
this.value = value;
}
public int getKey() {
return key;
}
public float getValue() {
return value;
}
}
public MapCursor<Integer, Float> getEntryCursor() {
return new EntryCursor();
}
protected class EntryCursor implements MapCursor<Integer, Float> {
private int index = 0;
private boolean removeCheck = false;
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(Float value) {
if (isValid())
values.set(index, value);
}
public Float value() {
if (isValid())
return values.get(index);
else
return null;
}
public Float remove() {
if (isValid()) {
Float value = values.get(index);
values.remove(index);
keys.remove(index);
removeCheck = true;
index--;
return value;
}
else {
return null;
}
}
}
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.get(index++));
}
public void remove() {
int removeindex = index - 1;
if (removeindex > 0) {
keys.remove(removeindex);
values.remove(removeindex);
index = removeindex;
}
}
}
}