Java中更好/更快的是:2个方法调用或1个对象调用

时间:2014-08-06 09:54:34

标签: java

我担心这是一个非常愚蠢的问题。但是,我找不到答案,因此需要一些帮助:)

让我们从简化我的真实问题开始:

假设我有几个装满各种宝石的盒子。

我现在正在创建一个具有属性颜色的对象gem和一个getColour方法来获取gem的颜色。 此外,我正在创建一个对象框,其中包含一个gems列表作为属性,另一个方法getGem用于从该列表中获取gem。

我现在要做的是按颜色计算所有框中的所有宝石。现在我可以做像

这样的事情
int sapphire = 0;
int ruby = 0;
int emerald = 0;

for(each box = i)
    for(each gem = j)
        if(i.getGem(j).getColour().equals(“blue”)) sapphire++;
        else if(i.getGem(j).getColour().equals(“red”)) ruby++;
        else if(i.getGem(j).getColour().equals(“green”)) emerald++;

或者我可以做

int sapphire = 0;
int ruby = 0;
int emerald = 0;
String colour;

for(each box = i)
    for(each gem = j)
        colour = i.getGem(j).getColour();
        if(colour.equals(“blue”)) sapphire++;
        else if(colour.equals(“red”)) ruby++;
        else if(colour.equals(“green”)) emerald++;

我现在的问题是,两者基本相同还是优先于另一个?我知道在第二种情况下会产生许多不必要的新字符串对象,但是由于颜色更“直接”可用,我是否会获得速度优势?

3 个答案:

答案 0 :(得分:2)

我敢于进行第三次改进:

int sapphire = 0;
int ruby = 0;
int emerald = 0;

for(each box = i) {
    for(each gem = j) {
        String colour = i.getGem(j).getColour();
        if(“blue”.equals(colour)) sapphire++;
        else if(“red”.equals(colour)) ruby++;
        else if(“green”.equals(colour)) emerald++;
    }
}
  1. 我在for循环中使用局部变量。为什么?因为你可能只需要它。
  2. 通常最好放置STATIC_STRING.equals(POSSIBLE_NULL_VALUE)。
  3. 这具有以下优点:更易于阅读且不存在性能问题。如果您遇到性能问题,那么您应该考虑查看代码中的其他位置。与此相关:this answer

答案 1 :(得分:2)

概念上,两个代码具有相同的复杂性,即:O(i * j)。但是如果调用方法并获得返回值被认为是两个进程,那么第一个代码的复杂性将是4 * O(i * j)。(将O(i * j)视为函数)和第二个代码的复杂性代码为O(i *(j + 2))。虽然这种复杂性差异不够大,但如果你比较那么肯定你的第一个代码更复杂,也不是一个好的编程风格。

答案 2 :(得分:1)

字符串比较的成本将消除这种方法中的所有其他注意事项。

您最好使用其他东西(例如enum)。那也会自动扩大。

(尽管你的每个循环都不是正确的Java语法,所以这有点奇怪)。

 enum GemColour {
     blue,
     red,
     green
 }

然后在你的计数功能中:

 Map<GemColour, Integer> counts = new EnumMap<GemColour, Integer>(GemColour.class);

 for (Box b: box) {
    for (Gem g: box.getGems() {
       Integer count = counts.get(g.getColour());
       if (count == null) { 
          count=1;
       } else {
          count+=1;
       }

       counts.put(g.getColour(), count);
    }
 }

现在它会自动扩展到您添加的任何新颜色,而无需进行任何代码更改。它也会更快,因为它进行单个整数比较而不是字符串比较,并使用它将正确的值放入地图中的正确位置(在幕后只是一个数组)。

要获得计数,例如:

counts.get(GemColour.blue);

正如评论中指出的那样,java Stream API允许你在一行中完成所有这些:

boxes.stream().map(Box::getGems).flatMap(Collection::stream).collect(groupingBy‌​‌​(Gem::getColour, counting()))

虽然不太容易理解它正在做什么。