BinaryOperator的身份

时间:2018-09-12 13:12:10

标签: java lambda java-8 functional-programming

我在Java8中的UnaryOperator接口中看到下面的代码,该代码对参数不执行任何操作并返回相同的值。

static <T> UnaryOperator<T> identity() {
    return t -> t;
}

BinaryOperator是否有任何东西可以接受相同种类的两个参数并返回一个值

static <T> BinaryOperator<T> identity() {
    return (t,t) -> t;
}

为什么我问这个问题是出于以下要求,

List<String> list = Arrays.asList("Abcd","Abcd");
Map<String,Integer> map = list.stream().collect(Collectors.toMap(str->str, 
str->(Integer)str.length(),(t1,t2)->t1));
System.out.println(map.size());

在上面的代码中,我不想为同一个键的两个值做任何事情,我只想返回一个值,因为在我的情况下,确定值将是相同的。 由于未使用t2值声纳抛出错误,所以我发现java8

中也存在 BinaryOpertor 之类的 UnaryOperator.identity()

3 个答案:

答案 0 :(得分:6)

您的问题确实没有道理。如果将提议的BinaryOperator.identity方法粘贴到IDE中,您将立即看到它会抱怨标识符t被声明两次。

要解决此问题,我们需要为每个参数使用不同的标识符:

return (t, u) -> t;

现在我们可以清楚地看到这不是 identity 函数。该方法需要两个参数并返回第一个参数。因此,最好的名字应该是getFirst

要回答有关JDK中是否存在类似内容的问题:。使用标识功能是一种常见的用例,因此定义一个方法非常有用。任意返回两个的第一个参数不是一个常见的用例,并且有一种方法可以做到这一点也没有用。

答案 1 :(得分:4)

T表示它们具有相同的类型,而不是相同的,这本身并不是一个身份。

这只是意味着BinaryOperator将用于相同的类型,但是为不同的值提供identity……听起来有点像foldLeftfoldRightfoldLeftIdentity/foldRightIdentity,java没有。

答案 2 :(得分:4)

您的代码似乎可以改进为

List<String> list = Arrays.asList("Abcd", "Abcd");
Map<String, Integer> map = list.stream()
            .collect(Collectors.toMap(Function.identity(), String::length, (a, b) -> a));
System.out.println(map.size());

或者对于您的用例 我不想为同一个键的两个值做任何事情,我只想返回一个值 ,您可以选择使用以下实现,随机返回任何值:

private static <T> BinaryOperator<T> any() {
    return Math.random() < 0.5 ? ((x, y) -> x) : ((x, y) -> y);
}

,然后在您的代码中将其用作

Map<String, Integer> map = list.stream()
            .collect(Collectors.toMap(Function.identity(), String::length, any()));

由于Holger,Eugene和Federico的建议,any方法的其他有效实现实际上可能涉及使用:

private static <T> BinaryOperator<T> any() {
    // suggested by Holger
    return ThreadLocalRandom.current().nextBoolean() ? ((x, y) -> x) : ((x, y) -> y);
    // suggested by Eugene
    long nt = System.nanoTime(); 
    ((nt >>> 32) ^ nt) > 0 ? ((x, y) -> x) : ((x, y) -> y);
}