【问题标题】:Java var type inference on generic parameter typeJava var 类型推断泛型参数类型
【发布时间】:2021-03-12 08:34:35
【问题描述】:

我有一个流收集器的合并功能,并试图使其通用。由于 lambda 接受 var 作为参数类型并且结果类型是 BinaryOperator,所以我试图获得类似 BinaryOperator> 或类似的东西。

BinaryOperator<InsertYourFavouriteType> rejectNewValueAndWarn = (oldValue, newValue ) -> {
            LOGGER.warn( "Old value already present in map, rejecting to collect new value" );
            LOGGER.warn( "Old value:" + oldValue );
            LOGGER.warn( "New value:" + newValue );
            return oldValue;
        };

这已经很通用了,但是我想摆脱泛型参数中的显式类型。

【问题讨论】:

  • 那么rejectNewValueAndWarn 应该在允许使用类型变量键入InsertYourFavouriteType 的上下文(泛型类或泛型方法)中声明。也许这是一个 XY 问题,请说明您要使用 rejectNewValueAndWarn 做什么。
  • @Lino 哦,我明白了。 OP 正在尝试将其用作collect 的组合器参数。

标签: java generics lambda type-inference


【解决方案1】:

你不能用变量直接1做到这一点,但使用方法完全可以:

public final class Rejecter {
    public static <T> T rejectNewValueAndWarn(T oldValue, T newValue) {
        LOGGER.warn("Old value already present in map, rejecting to collect new value");
        LOGGER.warn("Old value:" + oldValue);
        LOGGER.warn("New value:" + newValue);
        return oldValue;
    }
}

那么你可以使用方法引用来直接引用方法:

Map<A, B> map = whatever.stream()
    .collect(Collectors.toMap(
        ..., // your key mapper
        ..., // your value mapper
        Rejecter::rejectNewValueAndWarn // the merge function
    ));

1 您可以将泛型参数定义为?Object,但是您需要针对每种用法进行强制转换,例如(BinaryOperator&lt;SomeType&gt;) rejectNewValueAndWarn,这实际上消除了将此逻辑提取到一个公共位置。

【讨论】:

  • 感谢您的努力!我想出了几乎相同的解决方案 - 所以你的对我来说看起来不错:-D
【解决方案2】:

好的,在使用泛型类型作为类型参数的提示之后,我想出了一个合并函数,定义如下:

static < K > BinaryOperator< K > mergeFunction()
    {
        BinaryOperator< K > rejectNewValueAndWarn = ( oldValue, newValue ) -> {
            LOGGER.warn( "Old value already present in map, rejecting to collect new value" );
            LOGGER.warn( "Old value:" + oldValue );
            LOGGER.warn( "New value:" + newValue );
            return oldValue;
        };
        return rejectNewValueAndWarn;
    }

blablaList.
            .stream()
            .collect( Collectors.toMap( AbstractDto::getName, Function.identity(), mergeFunction() ) );

【讨论】:

  • 你应该直接返回 lambda,你应该将方法重命名为rejectNewValueAndWarn,这样无论在哪里使用,效果都会“记录在案”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-05
  • 1970-01-01
相关资源
最近更新 更多