package edu.berkeley.nlp.lm.map; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import edu.berkeley.nlp.lm.WordIndexer; import edu.berkeley.nlp.lm.collections.Iterators; import edu.berkeley.nlp.lm.util.Logger; /** * Wraps an NgramMap as an Iterable, so it is easy to iterate over the n-grams * and associated values. Using this interface is a little inefficient due to * the boxing and temporary object allocation necessary to conform to Java's * interfaces. * * @author adampauls * * @param <V> * @param <W> */ public class NgramIterableWrapper<W, V> implements Iterable<java.util.Map.Entry<List<W>, V>> { private final NgramsForOrderIterableWrapper<W, V>[] ngramsForOrder; public NgramIterableWrapper(final NgramMap<V> map, final WordIndexer<W> wordIndexer) { this(map, wordIndexer, map.getMaxNgramOrder()); } /** * * @param map * @param wordIndexer * @param maxOrder * this is 1-based (i.e. 1 means keep unigrams but not bigrams) */ public NgramIterableWrapper(final NgramMap<V> map, final WordIndexer<W> wordIndexer, final int maxOrder) { @SuppressWarnings("unchecked") final NgramsForOrderIterableWrapper<W, V>[] maps = new NgramsForOrderIterableWrapper[maxOrder]; ngramsForOrder = maps; for (int ngramOrder = 0; ngramOrder < maxOrder; ++ngramOrder) { ngramsForOrder[ngramOrder] = new NgramsForOrderIterableWrapper<W, V>(map, wordIndexer, ngramOrder); } } @Override public Iterator<Entry<List<W>, V>> iterator() { final Iterators.Transform<NgramsForOrderIterableWrapper<W, V>, Iterator<java.util.Map.Entry<List<W>, V>>> transform = new Iterators.Transform<NgramsForOrderIterableWrapper<W, V>, Iterator<java.util.Map.Entry<List<W>, V>>>( Arrays.asList(ngramsForOrder).iterator()) { @Override protected Iterator<java.util.Map.Entry<List<W>, V>> transform(final NgramsForOrderIterableWrapper<W, V> next) { return next.iterator(); } }; return new Iterators.IteratorIterator<Map.Entry<List<W>, V>>(transform); } public long size() { long size = 0; for (final NgramsForOrderIterableWrapper<W, V> map : ngramsForOrder) { size += map.size(); } if (size > Integer.MAX_VALUE) Logger.warn(NgramMapWrapper.class.getSimpleName() + " doesn't like maps with size greater than Integer.MAX_VALUE"); return (int) size; } }