我在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()答案 0 :(得分:6)
您的问题确实没有道理。如果将提议的BinaryOperator.identity
方法粘贴到IDE中,您将立即看到它会抱怨标识符t
被声明两次。
要解决此问题,我们需要为每个参数使用不同的标识符:
return (t, u) -> t;
现在我们可以清楚地看到这不是 identity 函数。该方法需要两个参数并返回第一个参数。因此,最好的名字应该是getFirst
。
要回答有关JDK中是否存在类似内容的问题:否。使用标识功能是一种常见的用例,因此定义一个方法非常有用。任意返回两个的第一个参数不是一个常见的用例,并且有一种方法可以做到这一点也没有用。
答案 1 :(得分:4)
T
表示它们具有相同的类型,而不是相同的值,这本身并不是一个身份。
这只是意味着BinaryOperator
将用于相同的类型,但是为不同的值提供identity
……听起来有点像foldLeft
或foldRight
或foldLeftIdentity/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);
}