嵌套 BiFunction 的深度(或限制,如果有)是多少 [英] What is the depth (or limitation if any) for nesting BiFunction

查看:23
本文介绍了嵌套 BiFunction 的深度(或限制,如果有)是多少的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在玩 BiFunction (java.util.function).我跑了一些例子,我有一个问题.

<块引用>

操作可以嵌套多少次有限制吗用双功能?是否像嵌套一个假设的 add(a, b) 一样简单想要多少次方法?

例如三个嵌套的 theFunction.apply()

public static int methodContainingMethod(int a, int b, int c, BiFunction theFunction) {返回 theFunction.apply(theFunction.apply(theFunction.apply(a,b),c),c),c);}

四个嵌套的theFunction.apply()

返回theFunction.apply(theFunction.apply(theFunction.apply(theFunction.apply(a,b),c),c),c),c);

<块引用>

不断......嵌套的数量可以不断增加,我测试过嵌套函数十次以上.

对于需要多少嵌套我没有确切的要求......但我很好奇可以完成多少这样的嵌套?

解决方案

首先,这绝不是针对 BiFunction 的.所以您基本上是在问,您可以将方法调用嵌套多深,简单的答案是 Java 编程语言本身没有指定限制.

存在可能会限制数量的技术限制,但这些都是技术限制,而不是规格限制.当技术发展而不改变规范时,它们可能会被取消.

正如 Alain O'Dea 所解释的,方法的代码大小限制为 65535 字节或 65534 字节,如果最后一条指令应该被异常处理程序覆盖.此代码大小支持的嵌套方法调用量取决于某些因素.例如,您正在使用 interface 和接口方法调用使用比具体类方法调用更多的字节(invokevirtual 指令),此外,您正在使用 BiFunction 而不是直接的 IntBinaryOperator,因此每次调用都涉及对需要额外代码的 int 值进行装箱.

但无论如何还有另一个技术限制,即编译器实现.当尝试使用更高的嵌套计数编译示例时,javac 从命令行运行,在 1500 次嵌套调用时以 stackoverflow 终止,而 Netbeans(使用与 javac) 在 IDE 开始表现出奇怪的行为之前设法编译了 2000 个嵌套调用(我猜,它不能很好地处理编译器/语法荧光笔的堆栈溢出).

这表明 IDE 具有更高的堆栈大小或环境设置中的其他差异影响了表达式被解析之前的初始堆栈深度.由此得出的结论是,实践中没有硬性限制.您可能能够编写一个编译器能够毫无问题地编译的代码,而另一个编译器却能顺利编译——这不是最大化这一点的好主意.

毕竟,你的问题代码的等价物可以写成:

public static int methodContainingMethod(int a, int b, int c, BiFunction功能) {int value = theFunction.apply(a, b);for(int i=0; i

虽然我认为,你的想法更像是:

public static int methodContainingMethod(IntBinaryOperator theFunction, int first, int second, int... rest) {int value = theFunction.applyAsInt(first, second);for(int next: rest) value=theFunction.applyAsInt(value, next);返回值;}

public static OptionalInt methodContainingMethod(IntBinaryOperator theFunction, int... arguments) {返回 IntStream.of(arguments).reduce(theFunction);}

I have been playing with BiFunction (java.util.function). I ran some examples and and I have one question.

Is there a limitation on how many times the operation can be nested with BiFunction? Is it as simple as nesting a hypothetical add(a, b) method as many times as one wants?

e.g. three nested theFunction.apply()

public static int methodContainingMethod
         (int a, int b, int c, BiFunction<Integer, Integer, Integer> theFunction) {
    return theFunction.apply(theFunction.apply(theFunction.apply(a,b),c),c),c);
}

four nested theFunction.apply()

return
  theFunction.apply(theFunction.apply(theFunction.apply(theFunction.apply(a,b),c),c),c),c);

on and on... The number of nesting can go up and on, I tested with nesting the function for over ten times.

I don't have exact requirement as to how many nesting is needed... but I am curious as to how many nesting of such can be done?

解决方案

First of all, that’s not specific to BiFunction in any way. So you are basically asking, how deep you can nest method invocations and the simple answer is that the Java programming language does not specify a limitation per se.

There are technical limitations which may restrict the number but these are, well, technical limitations, not limitation by specification. They might be lifted when the technology evolves without changes in the specification.

As Alain O'Dea has explained, a method’s code size is limited to 65535 bytes or to 65534 bytes if the last instruction ought to be covered by an exception handler. The amount of nested method calls supported by this code size depends on some factors. E.g., you are using an interface and interface method invocation use more bytes than concrete class method invocations (invokevirtual instructions), further, you are using BiFunction<Integer, Integer, Integer> rather than the straight-forward IntBinaryOperator so every invocation involves boxing of the int values which requires additional code.

But there is another technical limitation anyway, the compiler implementation. When trying to compile your example with a higher nesting count, javac ran from the command line terminated with a stackoverflow at 1500 nested invocation, while Netbeans (using the same compiler code as javac) managed to compile 2000 nested invocations before the IDE started to exhibit strange behavior (I guess, it doesn’t handle stack overflows of the compiler/ syntax highlighter very well).

That suggests that the IDE had a higher stack size or other differences in the environmental setup affected the initial stack depth before the expression got parsed. This leads to the conclusion that there is no hard limit in practice. You may be able to write code which one compiler manages to compile without problems whereas another one bails out— not a good idea to max this out.

After all, the equivalent of your question’s code could be written as:

public static int methodContainingMethod(
    int a, int b, int c, BiFunction<Integer, Integer, Integer> theFunction) {

    int value = theFunction.apply(a, b);
    for(int i=0; i<asDeepAsYouWannaGo; i++)
        value=theFunction.apply(value, c);
    return value;
}

though I think, what you have in mind, is more like:

public static int methodContainingMethod(
    IntBinaryOperator theFunction, int first, int second, int... rest) {

  int value = theFunction.applyAsInt(first, second);
  for(int next: rest) value=theFunction.applyAsInt(value, next);
  return value;
}

or

public static OptionalInt methodContainingMethod(
    IntBinaryOperator theFunction, int... arguments) {

  return IntStream.of(arguments).reduce(theFunction);
}

这篇关于嵌套 BiFunction 的深度(或限制,如果有)是多少的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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