package nl.helixsoft.util; import java.util.Comparator; import java.util.LinkedHashSet; import java.util.Set; import java.util.TreeSet; import com.google.common.collect.ForwardingMultiset; import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; import com.google.common.primitives.Ints; /** * This is like a SortedMultiset, but it sorts by frequency (i.e. Value) instead of by Key. * From: http://stackoverflow.com/a/4375211/3306, with modifications */ public class FreqSortMultiset<E> extends ForwardingMultiset<E> { /** * Belongs with FreqSortMultiset. */ // From: http://stackoverflow.com/a/4375211/3306 enum EntryComp implements Comparator<Multiset.Entry<?>> { DESCENDING() { @Override public int compare(final Entry<?> a, final Entry<?> b) { int result = Ints.compare(b.getCount(), a.getCount()); // If we return 0 if the objects are different, the objects will disappear from a sorted treeset. // So as a tiebreaker, we compare the stringified forms of a & b, which works even if a & b don't implement comparable. if (result == 0) result = a.toString().compareTo(b.toString()); return result; } }, ASCENDING() { @Override public int compare(final Entry<?> a, final Entry<?> b) { return -DESCENDING.compare(a, b); } } ; } private Multiset<E> delegate; private EntryComp comp; private FreqSortMultiset(Multiset<E> delegate, boolean ascending) { this.delegate = delegate; if (ascending) this.comp = EntryComp.ASCENDING; else this.comp = EntryComp.DESCENDING; assert (EntryComp.ASCENDING != null); //For some reason, EntryComp is occasionally unitialized... assert (EntryComp.DESCENDING != null); assert (this.comp != null); } @Override protected Multiset<E> delegate() { return delegate; } @Override public Set<Entry<E>> entrySet() { assert (comp != null); TreeSet<Entry<E>> sortedEntrySet = new TreeSet<Entry<E>>(comp); sortedEntrySet.addAll(delegate.entrySet()); return sortedEntrySet; } @Override public Set<E> elementSet() { Set<E> sortedEntrySet = new LinkedHashSet<E>(); for (Entry<E> en : entrySet()) sortedEntrySet.add(en.getElement()); return sortedEntrySet; } public static <E> FreqSortMultiset<E> create(boolean ascending) { return new FreqSortMultiset<E>(HashMultiset.<E> create(), ascending); } public static <E> FreqSortMultiset<E> create() { return new FreqSortMultiset<E>(HashMultiset.<E> create(), false); } /* * For Testing * public static void main(String[] args) { Multiset<String> s = FreqSortMultiSet.create(false); s.add("Hello"); s.add("Hello"); s.setCount("World", 3); s.setCount("Bye", 5); System.out.println(s.entrySet()); }*/ }