package edu.berkeley.nlp.util; import java.util.*; /** * Maintains a two-way map between a set of (objects, substate) pairs and contiguous integers from 0 * to the number of objects. It also maintains a map from (object, substate) pairs * to contiguous integers. Use get(i) to look up object i, and * indexOf(object) to look up the index of an object. * This class was modified to accomodate objects that can have several substates. * It is assumed that if an object is added several times, it will be with the * same number of substates. * * @author Dan Klein * @author Romain Thibaux */ public class SubIndexer <E> extends AbstractList<E> { List<E> objects; // Index from 0 to objects.size()-1 of a given object: Map<E, Integer> indexes; // Sub-indexes (indexes of substates) of the object whose index is i are [ subindexes(i), subindexes(i+1) [ List<Integer> subindexes; /** * Return the object with the given index * * @param index */ public E get(int index) { return objects.get(index); } /** * Returns the number of objects indexed (not the total number of substates) */ public int size() { return objects.size(); } /** * Returns the total number of substates */ public int totalSize() { return subindexes.get(subindexes.size()-1); } /** * Returns the index of the given object, or -1 if the object is not present * in the indexer. * * @param o * @return */ public int indexOf(Object o) { Integer index = indexes.get(o); if (index == null) return -1; return index; } public int subindexBegin(int index) { return subindexes.get(index); } public int subindexEnd(int index) { return subindexes.get(index+1); } /** * Constant time override for contains. */ public boolean contains(Object o) { return indexes.keySet().contains(o); } /** * Add an element to the indexer. If the element is already in the indexer, * the indexer is unchanged (and false is returned). * * @param e * @return */ public boolean add(E e, int numSubstates) { if (contains(e)) return false; objects.add(e); indexes.put(e, size() - 1); Integer previousSubindex = subindexes.get(subindexes.size()-1); subindexes.add(previousSubindex + numSubstates); return true; } public SubIndexer() { objects = new ArrayList<E>(); indexes = new HashMap<E, Integer>(); subindexes = new ArrayList<Integer>(); subindexes.add(0); } }