Multimap.inverse() 到(非多)地图(已知原始地图中的值是唯一的)

S1l*_*0rm 2 java multimap guava

Guava 中有什么东西可以让我将 Multimap 的逆作为(非多)Map 得到?

考虑以下:

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();
Run Code Online (Sandbox Code Playgroud)

问题是inverse()它又是一个Multimap,而不是一个Map。Guava 中有什么东西可以为我进行转换,还是我必须推出自己的实用功能?

Xae*_*ess 5

我能想到的最好的方法是使用多地图Maps.transformValues视图的地图视图(我在这里假设是 Java 8,否则使用Function代替方法引用):

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

使用 Java 8 流,以上将是:

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));
Run Code Online (Sandbox Code Playgroud)

或者如果您关心订单:

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));
Run Code Online (Sandbox Code Playgroud)

或者希望在番石榴 21 中:

static final Map<Token, Integer> PRECEDENCES =
        TOKENS.inverse().asMap().entrySet().stream()
                .collect(ImmutableMap.toImmutableMap(
                                Map.Entry::getKey,
                                e -> Iterables.getOnlyElement(e.getValue())));
Run Code Online (Sandbox Code Playgroud)