Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,对于字符串x,s.length()的运行时成本是多少?是O(1)还是O(n)?_Java_String - Fatal编程技术网

在Java中,对于字符串x,s.length()的运行时成本是多少?是O(1)还是O(n)?

在Java中,对于字符串x,s.length()的运行时成本是多少?是O(1)还是O(n)?,java,string,Java,String,我被告知代码如下: for (int i = 0; i < x.length(); i++) { // blah } 这是真的吗?字符串长度是否存储为string类的私有整数属性?或者String.length()真的遍历整个字符串来确定其长度吗?不,java字符串的长度是O(1),因为java的String类将长度存储为字段 您收到的建议适用于C语言和其他语言,但不适用于java。C的strlen遍历char数组,查找字符串的结尾。Joel在播客上谈到了这一点,但在C的上下文中

我被告知代码如下:

for (int i = 0; i < x.length(); i++) {
    // blah
}

这是真的吗?字符串长度是否存储为string类的私有整数属性?或者
String.length()
真的遍历整个字符串来确定其长度吗?

不,java字符串的长度是O(1),因为java的String类将长度存储为字段


您收到的建议适用于C语言和其他语言,但不适用于java。C的strlen遍历char数组,查找字符串的结尾。Joel在播客上谈到了这一点,但在C的上下文中。

根据,长度是字符串对象的一个字段。

我不知道链接的翻译效果如何,但请参见。简而言之,
#length()
的复杂性为O(1),因为它只是返回一个字段。这是不可变字符串的许多优点之一。

与到目前为止所说的相反,
String.length()
不能保证字符串中包含的字符数是一个常数时间操作。
String
类的javadocs和Java语言规范都不要求
String.length
是一个常量时间操作


然而,在Sun的实现中,
String.length()
是一个常量时间操作。归根结底,很难想象为什么任何实现都会使用此方法的非常量时间实现。

您应该知道,
length()
方法返回UTF-16代码点的数量,这并不一定与所有情况下的字符数相同


好的,这实际上影响你的可能性很小,但是知道它没有坏处。

字符串将长度存储在一个单独的变量中。因为字符串是不可变的,所以长度永远不会改变。 它只需要在创建时计算一次长度,这是在为其分配内存时发生的。
因此它是O(1)

如果你不知道你可以这样写:

for (int i = 0, l = x.length(); i < l; i++) {
    // Blah
}
for(int i=0,l=x.length();i

因为
l
的范围更小,所以它只是稍微干净了一点。

即使计算字符串的长度是O(n),总的复杂性仍然不是O(n^2)。长度只计算一次,并在for循环中用作边界值,而不是在每次迭代中计算。据我所知,边界值不会被缓存。如果要在循环中修改边界该怎么办?每次都会计算边界。记住,for循环的检查只是一个任意表达式。编译器并不真正关心其中的内容,也不能做出假设。您可以很容易地调用每次都返回不同内容的方法。在某些情况下,可以缓存边界值。例如,JIT编译器知道数组是什么样的,如果它能够确定变量本身在循环期间不会改变,那么它就知道foo.length的值不会改变。我不知道它对字符串是否也有同样的作用。在他的例子中,x是一个字符串引用,它可以指向循环中的另一个字符串对象。在这种情况下,每次都需要重新计算边界。我不知道JIT是否足够聪明,可以检查引用本身是否被重新分配。可能吧。不变性与此无关。您可以有一个可变字符串类来跟踪其长度,就像您可以使用不可变字符串(例如StringBuilder)一样。您可以有一个不可更改的字符串(C中的const char*),但不可更改性确实保证在创建对象时只需计算一次长度值。如果对象是可变的,那么每次调用mutator方法都需要新的计算。俗话说,现在付钱给我,或者以后再付钱。严格地说,你们都是对的;但同时发生会对整个事件造成影响。试图在数据结构异步更改时更新辅助字段基本上是不可能的,因此在可变字符串实现中,length()通常是计算的,而不是访问的。您完全正确,我忽略了这一重要细节。哎呀!请注意,代码仍将在每次迭代时执行方法调用(编译器不知道值不会更改)。将调用移到循环控制之外将消除方法调用。话虽如此,这不太可能导致此循环的执行时间发生太多变化现代JIT可能会注意到length()是返回最终原语值的最终类的简单getter,并用int值本身替换方法调用。sk--我似乎记得看到过一个测试length()的JIT优化的博客证明了这是真的。基本上,某些字符必须由两个字符值表示。由于length()是char[]数组的大小,因此可能与字符数不同。但是,正如sadie所说,这是非常罕见的。尽管如此,我认为可以安全地假设String.length始终是常数时间。。。因为你给出的理由。
for (int i = 0, l = x.length(); i < l; i++) {
    // Blah
}