Java 8中throwMerger的替代方案 [英] Alternative for throwingMerger in Java 8

查看:230
本文介绍了Java 8中throwMerger的替代方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现使用合并功能的自己的收集器。不幸的是,对于我的一些情况,我不能重用抛出 IllegalStateException 的以下JDK合并函数。

I'm implementing own collector that uses merge function. Unfortunately, for some of my cases, I can't reuse the following JDK merger function that thrown IllegalStateException.

java.util.stream.Collectors#throwingMerger

这是因为它具有私有访问修饰符,并且来自其他(非内部)类的访问受到限制。
但是,javadoc说如下:

It happens due to the fact that it has private access modifier and access from other(not inner) classes is restricted. However, javadoc says the following:


这可以用来强制假设所收集的元素是不同的

This can be used to enforce the assumption that the elements being collected are distinct

但是,正如我所见,java doc已经过时了。它不能使用。问题是JDK是否为java开发人员提供了类似功能的访问权限(类似方法,常量等),还是应该自己编写?

But, as I see, java doc is out of date. It can't be used. The question is whether JDK provides access to similar functionality for the java developers(similar method, constant etc) or one should write it on their own?

推荐答案

throwingMerger()实现如下

private static <T> BinaryOperator<T> throwingMerger() {
    return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
}

您可以在代码库中添加类似的方法,但是您应该知道合并的基本问题:异常消息不正确。该函数的第一个参数是旧值,而不是键。该函数无法使用该键,因此生成包含重复键的异常消息对于此合并函数是不可能的。

You could add a similar method to your code base, but you should be aware of the fundamental problem of that merger: the exception message is incorrect. The first argument to that function is the old value, not the key. The key is not available to this function, so producing an exception message including the duplicate key is impossible for this merge function.

因此,在此处修复此问题是不可能,这个函数是一个实现细节是好的,所以它可以在没有任何兼容性限制的情况下为Java 9删除。

So, since fixing this issue at this place is impossible, it’s good that this function is an implementation detail, so it could be removed for Java 9 without any compatibility constraints.

为了提供合理的诊断, toMap 没有合并函数需要一个完全不同的实现,而不是 toMap 和(非抛出)合并函数,所以 toMap toConcurrentMap 没有合并功能的收藏家已被完全重写。

For providing a reasonable diagnostic, toMap without merge function needs an entirely different implementation than toMap with (non-throwing) merge function, so the toMap and toConcurrentMap collectors without merge function have been entirely rewritten.

一个常见的原因要求抛出合并功能,是没有 toMap 重载接受没有合并功能的地图供应商。但是,由于投掷合并不会做正确的事情,并且当重复密钥被拒绝时需要完全不同的方法,您可以使用这个答案。稍微改进的版本是

A common reason for asking for the throwing merge function, is that there is no toMap overload accepting a map Supplier without the merge function. But since the throwing merger is not going to do the right thing and an entirely different approach is needed when duplicate keys should be rejected, you may use the collector of this answer instead. A slightly improved version of it is

public static <T, K, V, M extends Map<K,V>> Collector<T, ?, M> toMap(
        Function<? super T, ? extends K> keyMapper,
        Function<? super T, ? extends V> valueMapper,
        Supplier<M> mapSupplier) {

    return Collector.of(mapSupplier,
            (m,t) -> putUnique(m, keyMapper.apply(t),
                                  Objects.requireNonNull(valueMapper.apply(t))),
            (m1,m2) -> {
                if(m1.isEmpty()) return m2;
                if(!m2.isEmpty()) m2.forEach((k,v) -> putUnique(m1, k, v));
                return m1;
            });
}
private static <K, V> void putUnique(Map<K, V> map, K key, V v1){
    V v2 = map.putIfAbsent(key, v1);
    if(v2 != null) throw new IllegalStateException(
        String.format("Duplicate key %s (values %s and %s)", key, v1, v2));
}

这篇关于Java 8中throwMerger的替代方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆