2

我目前正在使用一个大容器,我需要迭代做很多事情。以下哪项被认为是更好的风格?

a) 大循环:

for (container::iterator it = myContainer.begin(); it < myContainer.end(); ++it) {
    // do thing a with *it

    // do thing d with *it

    // do thing c with *it

    // do thing b with *it
}

b) 小循环:

for (container::iterator it = myContainer.begin(); it < myContainer.end(); ++it) {
    // do thing a with *it
}

for (container::iterator it = myContainer.begin(); it < myContainer.end(); ++it) {
    // do thing b with *it
}

for (container::iterator it = myContainer.begin(); it < myContainer.end(); ++it) {
    // do thing c with *it
}

for (container::iterator it = myContainer.begin(); it < myContainer.end(); ++it) {
    // do thing d with *it
}

我发现 b) 更好读,因为 a) 会变得笨拙,非常容易理解。但是a)我认为会跑得更快。那么哪种风格更好呢?myContainer 将包含多达 10.000 个元素,并且必须重复此过程,因此性能很重要。

4

2 回答 2

6

将单独的任务拆分到不同的循环还有进一步的重构好处。

在处理大数据集时,循环性能并不总是很直接,因此您通常应该从可读性开始,并在需要时返回单循环。

这是 Martin Fowler 的拆分循环重构示例

你经常会看到同时做两件不同事情的循环,因为他们可以通过一个循环来做到这一点。事实上,大多数程序员会对这种重构感到非常不舒服,因为它会迫使您执行两次循环——这是工作量的两倍。

但就像许多优化一样,在一个循环中做两件不同的事情比单独做更清楚。它还会导致进一步重构的问题,因为它引入了阻碍进一步重构的临时性。所以在重构时,不要害怕摆脱循环。当你优化时,如果循环很慢,就会出现,并且在那个时候将循环重新组合在一起是正确的。您可能会惊讶于循环不是瓶颈的频率,或者后来的重构如何打开另一个更强大的优化。

原始代码

void printValues() {
  double averageAge = 0;
  double totalSalary = 0;
  for (int i = 0; i < people.length; i++) {
    averageAge += people[i].age;
    totalSalary += people[i].salary;
  }
  averageAge = averageAge / people.length;
  System.out.println(averageAge);
  System.out.println(totalSalary);
}

最初成为

void printValues() {
  double totalSalary = 0;
  for (int i = 0; i < people.length; i++) {
    totalSalary += people[i].salary;
  }

  double averageAge = 0;
  for (int i = 0; i < people.length; i++) {
    averageAge += people[i].age;
  }
  averageAge = averageAge / people.length;

  System.out.println(averageAge);
  System.out.println(totalSalary);
}

提取方法后清理代码

void printValues() {
  System.out.println(averageAge());
  System.out.println(totalSalary());
}

private double averageAge() {
  double result = 0;
  for (int i = 0; i < people.length; i++) {
    result += people[i].age;
  }
  return result / people.length;
}

private double totalSalary() {
  double result = 0;
  for (int i = 0; i < people.length; i++) {
    result += people[i].salary;
  }
  return result;
}
于 2015-06-30T12:29:53.010 回答
1

您应该使用单循环。您可以将循环内包含的代码重构为单独的函数。

将大循环分成四个较小的循环是相当低效的,它增加了多余的操作。

于 2012-06-22T14:48:12.383 回答