6

我多次有这个疑问,但没有找出正确的解决方案。这一次,我想清除它。我有这样的情况

1. 
String sNumber="ksadfl.jksadlf";
if(sNumber.lastIndexOf('.')>0)
   //do something
...
...
if(sNumber.lastIndexOf('.')>1)
 //do something
...

2.
int index = sNumber.lastIndexOf('.');
if(index>0)
//do something
...
...
if(index>1)
//do something
...

第一种方式和第二种方式之间的权衡是什么?哪一个更适合将结果存储在变量中或两次调用该函数?

4

4 回答 4

5

在此示例中,从性能角度来看,第二种形式更好(在大多数可能的情况下1 ),并且(IMO)更具可读性。

一般来说,有几个权衡需要考虑:

  • 可读性比效率更重要吗?
  • 调用该方法两次而不是一次对“性能影响”有多大?

此外,您还需要考虑该方法可能有副作用的情况,以及它是否可能在两次连续调用时给出不同的答案。在这些情况下,调用该方法两次在语义上与调用一次并将结果存储在临时变量中是不同的。


1 - 该index变量使堆栈帧大 1 个字。通常这无关紧要,但如果代码是在以深度递归方式调用的递归方法中,则 1 个额外的单词乘以嵌套调用的数量可能会导致StackOverflowError.

于 2013-04-20T07:15:44.540 回答
3

由于该问题仅涉及 2 个精益lastIndexOf电话,因此两者之间实际上几乎没有区别。如果它是通过代理的远程调用或数据库命中的东西,那么将方法结果存储到变量中会看到一些改进。

在此处输入图像描述

再次调用该方法的好处是您将始终获得索引的最新值,以防它在较早的块中的某个地方被操纵。在大多数情况下,#2 将是正确的选择,但对于您上面的确切示例,它是 #1。

于 2013-04-20T07:32:53.853 回答
2

你的怀疑是显而易见的。您的第二种方法既好又有效。

因为如果您的字符串变量数据每次都没有变化,那么就不需要每次都获取索引。不行,需要反复使用sNumber.lastIndexOf('.')。每次你的lastIndexOf()函数运行时,都需要额外的时间和其他资源。

因此,最好使用第二个选项,这会使您的程序更快更短。

于 2013-04-20T05:19:15.710 回答
1

您的问题是内存使用率和 CPU 使用率之间的经典权衡。

首先,您必须确定您是否希望您的程序在内存中占用较小的内存,或者您是否希望它快速运行。解决方案 1 很可能会导致最少的内存使用(因为您没有存储 int),而解决方案 2 将导致最快的执行时间,因为您不必进行两次 indexOf 计算。

话虽如此,将计算存储在内存中并不总是会产生最快的程序。具有较小的内存占用通常会导致较少的缓存未命中。缓存未命中通常比简单地计算两次要慢得多。

要了解最小化缓存未命中的重要性,请查看这篇关于 C++ 中列表与向量的性能的帖子。人们会期望列表比向量快得多,因为不必复制数据。然而,列表实现确实有更多的随机数据访问,因此更多的缓存未命中导致向量更快。

最后,我建议您衡量两种解决方案的性能,并确定您最喜欢哪种内存和 CPU 使用率组合。

于 2013-04-20T07:34:17.050 回答