Collect all items containing a word to a Multimap I have a simple class like

class Item {
    Set&lt;String&gt; wordSet() {...}
}


So each item has a set of words and I need the inverse relation, i.e., for each word find all items containing it. This gets used a lot, so I want an ImmutableSetMultimap allowing me to retrieve it quickly.

I'm using

ImmutableSetMultimap&lt;String, Item&gt; wordToItemsMultimap(Collection&lt;Item&gt; items) {
    Multimap&lt;Item, String&gt; itemToWords = items
        .stream()
        .collect(Multimaps.flatteningToMultimap(
             i -&gt; i,
             i -&gt; i.wordSet().stream(),
             HashMultimap::create));
    Multimap&lt;String, Item&gt; wordToItems =
             Multimaps.invertFrom(itemToWords, HashMultimap.create());
    return ImmutableSetMultimap.copyOf(wordToItems);
}


for creating the map and it works, but I find it too complicated. I'm looking for a simpler solution.

I don't care much about efficiency of the above snippet (as it gets called just once), but optimization hints are welcome as I'm doing a lot of similar things where speed matters.
Well, if your items has no null elements, you can use ImmutableSetMultimap#flatteningToImmutableSetMultimap collector and it's own inverse method instead of calling utility methods.

return items.stream()
        .collect(flatteningToImmutableSetMultimap(
                i -&gt; i,
                i -&gt; i.wordSet().stream()
        ))
        .inverse();


It's a bit more terse (note the static import, which in my team we agreed is acceptable, although we normally don't use static imports) as it repeats looong class name in method name) and gives you immutable multimap right away.

If some "flattening" version of Multimaps#index existed, you could have also used it, but there's no such method right now unfortunately.