Java - 是否有 return ImmutableMap 的流收集器?
Java - Are there any Stream Collectors that return ImmutableMap?
我发现自己想要 Collectors.toMap
的变体,其中 returns 和 ImmutableMap
,这样我可以做到:
ImmutableMap result = list.stream().collect(MyCollectors.toImmutableMap(
tuple -> tuple._1(), tuple -> tuple._2());
(在此特定示例中,tuple
是 Scala Tuple2
)
我 just learned 这样的方法将在 Guava 21 中得到 Java-8 支持(耶!),但这听起来还需要 6 个月的时间。有谁知道今天可能实施此功能的任何现有图书馆(等)?
ImmutableMap
不是严格要求的,但似乎是我需要的最佳选择:按键查找,并保留原始迭代顺序。不变性也是首选。
请注意 FluentIterable.toMap(Function)
是不够的,因为我需要键映射函数和值映射函数。
由于我还没有找到这样的收藏家图书馆,所以我将分享我对我需要的特定图书馆的第一次尝试。这里没有风吹草动! (例如处理或合并重复键。)
请随时提出改进建议。
/**
* 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();
}
};
}
您不需要为此收集器编写匿名 class。您可以使用 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);
}
或者,如果您不介意先将结果收集到可变映射中,然后再将数据复制到不可变映射中,则可以结合使用 built-in toMap
收集器和 collectingAndThen
:
ImmutableMap<String, String> result =
list.stream()
.collect(collectingAndThen(
toMap(
tuple -> tuple._1(),
tuple -> tuple._2()),
ImmutableMap::copyOf));
我发现自己想要 Collectors.toMap
的变体,其中 returns 和 ImmutableMap
,这样我可以做到:
ImmutableMap result = list.stream().collect(MyCollectors.toImmutableMap(
tuple -> tuple._1(), tuple -> tuple._2());
(在此特定示例中,tuple
是 Scala Tuple2
)
我 just learned 这样的方法将在 Guava 21 中得到 Java-8 支持(耶!),但这听起来还需要 6 个月的时间。有谁知道今天可能实施此功能的任何现有图书馆(等)?
ImmutableMap
不是严格要求的,但似乎是我需要的最佳选择:按键查找,并保留原始迭代顺序。不变性也是首选。
请注意 FluentIterable.toMap(Function)
是不够的,因为我需要键映射函数和值映射函数。
由于我还没有找到这样的收藏家图书馆,所以我将分享我对我需要的特定图书馆的第一次尝试。这里没有风吹草动! (例如处理或合并重复键。)
请随时提出改进建议。
/**
* 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();
}
};
}
您不需要为此收集器编写匿名 class。您可以使用 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);
}
或者,如果您不介意先将结果收集到可变映射中,然后再将数据复制到不可变映射中,则可以结合使用 built-in toMap
收集器和 collectingAndThen
:
ImmutableMap<String, String> result =
list.stream()
.collect(collectingAndThen(
toMap(
tuple -> tuple._1(),
tuple -> tuple._2()),
ImmutableMap::copyOf));