保留顺序收集到 Multimap 中

Collect into Multimap with order preserved

我有一个属性列表,如 attr1attr2 等。我还有一个函数接受一个属性和 returns 一个前缀列表。


private List<String> getAttributePrefixes(String attribute) {
 //get prefix for attribute
}

我想创建一个映射,其键是前缀,值是属性。由于前缀可以重复,所以我想将结果输出为multimap。

因此,对于上面的示例,输出 Multimap 将如下所示:

{ 
  a = [attr1, attr2],
  at = [attr1, attr2],
  att = [attr1, attr2],
  attr = [attr1, attr2],
  attr1 = [attr1],
  attr2 = [attr2]
}

我的代码存在的问题是没有保留顺序。例如,我的地图中的条目如下所示:

a = attr2, attr1 (I call getAttributePrefixes function first for attr1 and then attr2)

我要 attr1 先到,然后 attr2。这是我的代码:


Multimap<String, String> multimap = attributes.stream()
                                              .map(attribute -> new AbstractMap.SimpleEntry<>(attribute, getAttributePrefixes(attribute)))
                                              .flatMap(entry -> entry.getValue()
                                                                     .stream()
                                .map(prefix -> new AbstractMap.SimpleEntry<>(prefix, entry.getKey())))
                                                      .collect(ImmutableListMultimap.toImmutableListMultimap(Map.Entry::getKey, Map.Entry::getValue));

主要问题是 stream 通常不提供或很少提供顺序保证,因为它是在考虑并行执行的情况下创建的。一个简单的选择是尝试 jOOλ 作为为单线程执行而实现的直接替换。它还为您的用例提供了一个不错的 groupBy 方法。

如果这不是 option/working,您必须手动执行分组才能获得排序。

    Map<String, List<String>> multimap = attributes.stream()
        .map(attribute -> new AbstractMap.SimpleEntry<>(attribute, getAttributePrefixes(attribute)))
        .flatMap(entry -> entry.getValue()
            .stream()
            .map(prefix -> new AbstractMap.SimpleEntry<>(prefix, entry.getKey())))
        .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList())));

groupingBy 是一个非并行收集器,所以它应该可以工作。不过,您需要将给定的地图包装成多重地图。