最近又参加了几场面试,非常幸运遇到一个非常好的面试官在编码的时候给我反馈,让我收获了一些编码规范上的新认识,虽然都是些很细小的东西,但感觉还是很有价值的。
image.png

循环的写法

常见的循环写法有 for 循环、while 循环,但是让你选择一个使用,会选择哪个?为什么?来看看一个简单题目:

给出一个字符串,若出现连续的奇数个空格,则将空格删除,其余情况不用管,返回最终的字符串。 例如 “a+++b++c++” (+代替空格),则最终的输出是 “ab++c++”

面试的时候遇到这种题目别提有多开心了,很快就可以写出这样的代码:

  1. public String delBlank(String in) {
  2. StringBuilder bd = new StringBuilder();
  3. for (int i = 0; i < in.length(); i++) {
  4. if (in.charAt(i) == ' ') { // 遇到空格,特殊处理
  5. int cnt = 0, j = i;
  6. while (j < in.length() && in.charAt(j) == ' ') {
  7. j++;
  8. cnt++;
  9. }
  10. if ((cnt & 1) == 0) { // 偶数情况添加空格
  11. for (int k = 0; k < cnt; k++) {
  12. bd.append(' ');
  13. }
  14. }
  15. i = j - 1; // attention!
  16. } else {
  17. bd.append(in.charAt(i));
  18. }
  19. }
  20. return bd.toString();
  21. }

这段代码虽然逻辑上没有什么问题,但是总是有一个地方不是那么顺眼:第 15 行 i = j - 1。可以看出,这一步操作是为了让 i 顺从 for 循环的逻辑,而生硬地增加了 -1 这个操作。这种方式对于代码阅读非常不友好:

  • 编写易出错。实话说,我第一次写这个代码的时候写的就是 i = j,最后是写了一个样例测试之后才发现了这个隐蔽的错误。
  • 他人阅读时容易疑惑。当看到 for 循环中的 i++ 后,大部分人都会形成 i 每一轮都增加 1 这种预期。此时,内部突然加上对 i 的修改操作,就一下子打断了之前建立的预期,让思路非常不顺畅。

所以,如果需要手动修改循环变量的时候,请使用 while 循环;使用 for 循环,那么请保证循环变量只由 for 本身修改。

if else

条件判断分支数尽量不要太多,能合并的情况请合并起来。看一个最长公共子串的例子:

  1. public int maxCommonSubString(String a, String b) {
  2. int na = a.length(), nb = b.length(), res = 0;
  3. int[][] dp = new int[na][nb];
  4. for (int i = 0; i < na; i++) {
  5. for (int j = 0; j < nb; j++) {
  6. if (a.charAt(i) == b.charAt(j)) {
  7. if (i > 0 && j > 0) {
  8. dp[i][j] = dp[i-1][j-1] + 1;
  9. } else if (i == 0) { // attention
  10. dp[0][j] = 1;
  11. } else if (j == 0) { // attention
  12. dp[i][0} = 1;
  13. }
  14. } else {
  15. dp[i][j] = 0;
  16. }
  17. res = Math.max(res, dp[i][j]);
  18. }
  19. }
  20. return res;
  21. }

这个是我最开始写的版本,仔细一看,其实 7~13 处的 if-else 逻辑是可以进一步简化的,因为 i 或者 j 无论哪个等于 0,都是 dp[i][j] = 0。

  1. if (i > 0 && j > 0) {
  2. dp[i][j] = dp[i-1][j-1] + 1;
  3. } else {
  4. dp[i][j] = 1;
  5. }

总结

使用 for 循环时,不要在循环内部修改循环变量的值,否则请使用 while 循环;if-else 的分支尽量减少,简洁化代码。这些代码的细节,如果没有他人的指出还真挺难察觉的,慢慢积累吧。