/******************************************************************************* * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package hr.fer.zemris.vhdllab.applets.editor.schema2.misc; import java.util.HashMap; import java.util.TreeSet; /** * * @author Axel * * @param <Tp> * Must have implemented equals and hashCode, and must be Comparable. */ public class CostSortedHash<Key extends Comparable<Key>, Tp> { private static class CostWrapper<K extends Comparable<K>> implements Comparable<CostWrapper<K>> { public int cost; public K key; public CostWrapper(int c, K k) { cost = c; key = k; } public int compareTo(CostWrapper<K> other) { if (this.cost < other.cost) return -1; if (this.cost > other.cost) return 1; return this.key.compareTo(other.key); } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof CostWrapper)) return false; CostWrapper other = (CostWrapper) obj; return this.cost == other.cost && this.key.equals(other.key); } @Override public int hashCode() { return cost << 16 + key.hashCode(); } } private static class TpWrapper<T> { public T value; public int cost; public TpWrapper(int c, T val) { cost = c; value = val; } } /* private fields */ private CostWrapper<Key> finder; private HashMap<Key, TpWrapper<Tp>> hash; private TreeSet<CostWrapper<Key>> tree; /* ctors */ public CostSortedHash() { finder = new CostWrapper<Key>(0, null); hash = new HashMap<Key, TpWrapper<Tp>>(); tree = new TreeSet<CostWrapper<Key>>(); } /* methods */ public boolean add(Key key, int cost, Tp elem) { if (hash.containsKey(key)) return false; /* add to hash */ hash.put(key, new TpWrapper<Tp>(cost, elem)); /* add to tree */ tree.add(new CostWrapper<Key>(cost, key)); return true; } public Tp get(Key key) { TpWrapper<Tp> t = hash.get(key); return (t != null) ? (t.value) : (null); } public Key cheapest() { CostWrapper<Key> cw = tree.first(); return (cw == null) ? (null) : (cw.key); } public boolean isEmpty() { return hash.isEmpty(); } public int size() { return hash.size(); } public boolean contains(Key key) { return hash.containsKey(key); } public boolean remove(Key key) { if (!hash.containsKey(key)) return false; /* remove from tree */ finder.cost = hash.get(key).cost; finder.key = key; tree.remove(finder); /* remove from hash */ hash.remove(key); return true; } /** * @throws IllegalArgumentException * U slucaju da key nije u kolekciji. */ public int getCost(Key key) { TpWrapper<Tp> tpw = hash.get(key); if (tpw == null) throw new IllegalArgumentException("Not in collection."); return tpw.cost; } public boolean updateCost(Key key, int cost) { if (!hash.containsKey(key)) return false; /* update tree */ TpWrapper<Tp> tpw = hash.get(key); finder.cost = tpw.cost; finder.key = key; tree.remove(finder); tree.add(new CostWrapper<Key>(cost, key)); /* update hash */ tpw.cost = cost; return true; } }