Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multimap.inverse() to a (non-multi) Map (values in original map known to be unique)

Is there something in Guava that allows me to get the inverse of a Multimap as a (non-multi-) Map?

Consider the following:

static final ImmutableMap<Token, Integer> precedences =
      new ImmutableSetMultimap.Builder<Integer, Token>()
      .put(0, NOT)
      .put(1, ASSIGN)
      .put(2, OR)
      .put(3, AND)
      .putAll(4, NOT_EQUAL, EQUALS)
      .putAll(5, LESS_EQUAL, LESS, GREATER_EQUAL, GREATER)
      .putAll(6, ADD, SUB)
      .putAll(7, MUL, DIV, MOD).build().inverse();

The problem is that the inverse() is a Multimap again, and not a Map. Is there something in Guava that does the conversion for me or do I have to roll my own utility function?

like image 567
S1lentSt0rm Avatar asked Oct 27 '25 14:10

S1lentSt0rm


1 Answers

The best I can think of is to use map view of a multimap and Maps.transformValues view (I'm assuming Java 8 here, otherwise use Function instead of method reference):

static final ImmutableMap<Token, Integer> PRECEDENCES = ImmutableMap.copyOf(
        Maps.transformValues(TOKENS.inverse().asMap(), Iterables::getOnlyElement));

Using Java 8 streams the above would be:

static final Map<Token, Integer> PRECEDENCES =
        TOKENS.inverse().asMap().entrySet().stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toMap(
                                Map.Entry::getKey,
                                e -> Iterables.getOnlyElement(e.getValue())),
                        ImmutableMap::copyOf));

or if you care about the order:

static final ImmutableMap<Token, Integer> PRECEDENCES =
        TOKENS.inverse().asMap().entrySet().stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toMap(
                                Map.Entry::getKey,
                                e -> Iterables.getOnlyElement(e.getValue()),
                                (u, v) -> {
                                    throw new IllegalStateException(String.format("Duplicate key %s", u));
                                },
                                LinkedHashMap::new),
                        ImmutableMap::copyOf));

or hopefully in Guava 21:

static final Map<Token, Integer> PRECEDENCES =
        TOKENS.inverse().asMap().entrySet().stream()
                .collect(ImmutableMap.toImmutableMap(
                                Map.Entry::getKey,
                                e -> Iterables.getOnlyElement(e.getValue())));
like image 197
Xaerxess Avatar answered Oct 30 '25 07:10

Xaerxess



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!