8

我在 UnaryOperator Interface 中的 Java8 中看到了一段代码,它对参数没有任何作用并返回相同的值。

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 中是否有类似UnaryOperator.identity ()BinaryOperator.identity ()

4

3 回答 3

6

你的问题真的没有意义。如果您要将建议BinaryOperator.identity的方法粘贴到 IDE 中,您会立即看到它会抱怨标识符t被声明了两次。

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

return (t, u) -> t;

现在我们可以清楚地看到这不是等函数。这是一个接受两个参数并返回第一个参数的方法。因此,最好的名称是getFirst.

要回答您关于 JDK 中是否有类似内容的问题:没有。使用标识函数是一个常见的用例,因此为此定义一个方法很有用。任意返回两个的第一个参数不是一个常见的用例,并且有一个方法来做到这一点也没有用。

于 2018-09-12T14:05:08.787 回答
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);
}
于 2018-09-12T13:18:21.900 回答
4

T意味着它们具有相同的类型,不同的,这本身不是一个身份。

它只是意味着BinaryOperator它将用于相同的类型,但identity为不同的值提供一个......这听起来像foldLeftor foldRightor foldLeftIdentity/foldRightIdentity,这是java所没有的。

于 2018-09-12T13:15:05.623 回答