package edu.berkeley.nlp.lm.collections; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.concurrent.Semaphore; /** * Maintains a two-way map between a set of objects and contiguous integers from * 0 to the number of objects. * * @author Dan Klein * @author Adam Pauls */ public class Indexer<E extends Comparable<E>> implements Serializable { private static final long serialVersionUID = -8769544079136550516L; protected ArrayList<E> objects; protected TIntMap<E> indexes; protected boolean locked = false; private Semaphore sem; public void lock() { this.locked = true; } public E getObject(final int index) { return objects.get(index); } public boolean add(final E elem) { final int oldSize = size(); return getIndex(elem) >= oldSize; } /** * Returns the number of objects indexed. */ public int size() { return objects.size(); } /** * Returns the index of the given object, or -1 if the object is not present * in the indexer. * * @param o * @return */ public int indexOf(final E o) { final int index = indexes.get(o, -1); return index; } /** * Return the index of the element If doesn't exist, add it. */ public int getIndex(final E e) { if (e == null) return -1; if (sem != null) sem.acquireUninterruptibly(); int index = indexes.get(e, -1); if (index < 0) { if (locked) throw new RuntimeException("Attempt to add to locked indexer"); index = size(); objects.add(e); assert size() >= 0 : "Too many objects in indexer"; indexes.put(e, index); } if (sem != null) sem.release(); return index; } public Indexer(final boolean sync) { objects = new ArrayList<E>(); indexes = new TIntMap<E>(); this.sem = sync ? new Semaphore(1) : null; } public Indexer() { this(false); } public Indexer(final Collection<? extends E> c) { this(); for (final E a : c) getIndex(a); } /** * Save some space my compacting underlying maps and lists. */ public void trim() { objects.trimToSize(); // indexes.switchToSortedList(); } public Iterable<E> getObjects() { return Collections.unmodifiableList(objects); } }