6

I have a Guava Multiset<Integer> and would like to iterate independently through entries sorted on (a) element value and (b) element count. I have used Simplest way to iterate through a Multiset in the order of element frequency? as

ImmutableMultiset<Integer> entryList = Multisets.copyHighestCountFirst(myIntegerMultiset);
for (Integer i : entryList) {
    System.out.println("I"+i);
}

but this returns all entries, whereas I would like a sorted list of Multiset.Entry<Integer> (one per unique value) which would allow me to get the count.

Independently I would like to get the same list of Multiset.Entry<Integer> sorted by the value of <Integer>.

Community
  • 1
  • 1
peter.murray.rust
  • 37,407
  • 44
  • 153
  • 217

2 Answers2

11
Iterable<Multiset.Entry<Integer>> entriesSortedByCount = 
   Multisets.copyHighestCountFirst(multiset).entrySet();
Iterable<Multiset.Entry<Integer>> entriesSortedByValue =
   ImmutableSortedMultiset.copyOf(multiset).entrySet();

Basically, you just need the entrySet(), instead of iterating over the Multiset itself.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • You're making a SortedMultiset copy of the original multiset, which sorts elements by their value, and then getting the entrySet from that. Is that what you were confused about? – Louis Wasserman Sep 30 '13 at 20:53
  • I think it's clear now - the copying operation is the way of constructing an ImmutableSortedMultiset which presumably doesn't have a public constructor. And the act of creation initiates a sort automatically. – peter.murray.rust Oct 01 '13 at 19:48
  • Correct. It's like a `TreeSet`, where the `new TreeSet(collection)` automatically creates a sorted `TreeSet` copy of the collection, except with a more descriptive name including the word "copy." – Louis Wasserman Oct 01 '13 at 21:18
  • From the javadoc comments it looks like the order of elementSet() for the `copyHighestCountFirst()` map is an implementation detail which might go away any time. `copyHighestCountFirst` only guarantees the `iterator()` order, not `entrySet()` order. From `Multiset#entrySet()` javadoc: `...The order of the elements in the element set is unspecified.` – Danstahr Jun 09 '16 at 10:40
  • From the ImmutableCollection Javadocs: "Deterministic iteration. The iteration order is always well-defined, depending on how the collection was created (see the appropriate factory method for details). View collections such as Multiset.elementSet() iterate in the same order as the parent, except as noted." – Louis Wasserman Jun 09 '16 at 15:10
2

You could get a set of entries and then sort it however you need.

Here is how you get a set of entries:

Set<Multiset.Entry<Integer>> entries = myIntegerMultiset.entrySet();

And then to sort we can define two comparators:

Comparator<Multiset.Entry<Integer>> byCount = new Comparator<Multiset.Entry<Integer>>() {
    int compare(Multiset.Entry<Integer> e1, Multiset.Entry<Integer> e2) {
        return e2.getCount() - e1.getCount();
    }
}

Comparator<Multiset.Entry<Integer>> byValue = new Comparator<Multiset.Entry<Integer>>() {
    int compare(Multiset.Entry<Integer> e1, Multiset.Entry<Integer> e2) {
        return e2.getElement() - e1.getElement();
    }
}

Then you can provide the comparators to a tree set to get a sorted collection:

Set<Multiset.Entry<Integer>> entries = myIntegerMultiset.entrySet();
Set<Multiset.Entry<Integer>> entriesSortedByCount = Sets.newTreeset(byCount);
entriesSortedByCount.addAll(entries);
Set<Multiset.Entry<Integer>> entriesSortedByValue = Sets.newTreeset(byValue);
entriesSortedByValue.addAll(entries);

Actually, Louis Wasserman's answer is much better, but I will post this one too in case you wanted to customize your sorting.

siledh
  • 3,268
  • 2
  • 16
  • 29
  • 1
    The second comparator is dangerous -- if the `Integer` values can be positive and negative, overflow can result in incorrect comparisons. Prefer `Ints.compare(int, int)`, or `Integer.compare`, if you're on Java 7. (It's okay in the first case, since subtracting nonnegative values can never overflow, but it's worth being wary.) – Louis Wasserman Sep 30 '13 at 17:52
  • +1 since it's useful to know the Comparator approach (and to know the dangers). – peter.murray.rust Sep 30 '13 at 18:04
  • + 1 since I was stuck in an environment where I could access only Guava 13, which does not have the `copyHighestCountFirst()` method. – seinecle May 02 '17 at 13:33