我发现自己想要一个Collectors.toMap
的变体,它会返回ImmutableMap
,这样我才能做到:
ImmutableMap result = list.stream().collect(MyCollectors.toImmutableMap(
tuple -> tuple._1(), tuple -> tuple._2());
(此特定示例中的tuple
是Scala Tuple2
)
我已经just learned这种方法将在Guava 21中提供Java-8支持(耶!)但这听起来好一个月之后。有谁知道今天可能实现这个的任何现有库(等)?
ImmutableMap
并非严格要求,但似乎是我要求的最佳选择:按键查找,并保留原始迭代顺序。不变性也是首选。
注意FluentIterable.toMap(Function)
是不够的,因为我需要键映射函数和值映射函数。
答案 0 :(得分:19)
您不需要为此收集器编写匿名类。您可以改为使用Collector.of
:
public static <T, K, V> Collector<T, ?, ImmutableMap<K,V>> toImmutableMap(
Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper) {
return Collector.of(
ImmutableMap.Builder<K, V>::new,
(b, e) -> b.put(keyMapper.apply(e), valueMapper.apply(e)),
(b1, b2) -> b1.putAll(b2.build()),
ImmutableMap.Builder::build);
}
或者,如果您不介意首先将结果收集到可变映射中,然后将数据复制到不可变映射中,则可以使用内置toMap
收集器与collectingAndThen
结合使用:
ImmutableMap<String, String> result =
list.stream()
.collect(collectingAndThen(
toMap(
tuple -> tuple._1(),
tuple -> tuple._2()),
ImmutableMap::copyOf));
答案 1 :(得分:0)
由于我还没有找到这样的收藏家图书馆,所以我会在我需要的具体问题上分享我的第一个错误。这里没有钟声或口哨声! (例如处理或合并重复的密钥。)
请随时提出改进建议。
/**
* A variant of {@link Collectors#toMap(Function, Function)} for immutable maps.
* <p>
* Note this variant throws {@link IllegalArgumentException} upon duplicate keys, rather than
* {@link IllegalStateException}
*
* @param <T> type of the input elements
* @param <K> output type of the key mapping function
* @param <V> output type of the value mapping function
* @param keyMapper a mapping function to produce keys
* @param valueMapper a mapping function to produce values
*
* @return a {@code Collector} which collects elements into a {@code Map} whose keys and values
* are the result of applying mapping functions to the input elements
*
* @throws IllegalArgumentException upon duplicate keys
*/
public static <T, K, V> Collector<T, ?, ImmutableMap<K,V>> toImmutableMap(
Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper) {
return new Collector<T, ImmutableMap.Builder<K,V>, ImmutableMap<K,V>>() {
public Supplier<Builder<K, V>> supplier() {
return ImmutableMap.Builder::new;
}
public BiConsumer<Builder<K, V>, T> accumulator() {
return (builder, element) -> {
K key = keyMapper.apply(element);
V value = valueMapper.apply(element);
builder.put(key, value);
};
}
public BinaryOperator<Builder<K, V>> combiner() {
return (b1, b2) -> {
b1.putAll(b2.build());
return b1;
};
}
public Function<Builder<K, V>, ImmutableMap<K, V>> finisher() {
return builder -> builder.build();
}
public Set<Collector.Characteristics> characteristics() {
return ImmutableSet.of();
}
};
}