在这里调用实例方法还是声明变量更好?

3
这里有两种方法可以合并两个有序的扑克牌子堆成为一个有序的扑克牌堆:
方法一:
public static Deck merge(Deck d1, Deck d2) {
  Deck result = new Deck(d1.cards.length + d2.cards.length);
  int i = 0;
  int j = 0;

  for (int k = 0; k < result.cards.length; k++) {
    if (j >= d2.cards.length || i < d1.cards.length && d1.cards[i].compareTo(d2.cards[j]) <= 0) {
      result.cards[k] = d1.cards[i];
      i++;
    } else {
      result.cards[k] = d2.cards[j];
      j++;
    }
  }
  return result;
}

方法2:

public static Deck merge(Deck d1, Deck d2) {
  Deck result = new Deck(l1+l2);
  Card[] c1 = d1.getCards();
  Card[] c2 = d2.getCards();
  int l1 = c1.length;
  int l2 = c2.length;
  Card[] sorted = new Card[l1+l2];
  int i = 0;
  int j = 0;

     for (int k = 0;k<sorted.length;k++){
        if (j >= c2.length || i < c1.length && c1[i].compareTo(c2[j]) <= 0){
           sorted[k] = c1[i];
           i++;
        } 
        else {
           sorted[k] = c2[j];
           j++;
        }
     }
  }
  result.cards = sorted;
  return result;
}

哪种方法更有效?它们真的有什么区别吗?

据我所知,第一种方法需要生成更多的对象来完成运行,比如说两个26张牌的子牌组。然而,该方法本身存储的信息较少,这让我怀疑哪种方法更有效。

我知道在这个规模上可能并不太重要,但作为一个新手,我很想知道什么是最佳实践以及为什么。我尝试搜索类似的情况,但没有找到任何。如果有人能指点我方向,我将不胜感激。


你能发一下你的Deck类吗?看看这个类是关于什么的会很有用。 - whiplash
方法二无法编译——deck在哪里声明?你认为为什么方法一会创建更多的对象?看起来它创建的对象更少——两种方法都创建了一个新的Deck,而方法二还创建了一个Card[] - tgdavies
@tgdavies 在返回值中有一个错误。已将其更新为结果。 - Josh Hardman
@tgdavies。在方法一中使用的.cards是对Card对象的引用。如果您感兴趣,这是Card类的链接... https://github.com/AllenDowney/ThinkJavaCode/blob/master/ch12/Card.java - Josh Hardman
@Sweeper 我正在尝试理解在这种情况下实例化Card类的最佳方法。在这种情况下,Card和Deck都是对象。 - Josh Hardman
显示剩余6条评论
2个回答

2
由于 getCards() 仅返回引用变量(即它不会复制 cards 数组),因此性能差异可能很小。
唯一确定的方法是对应用程序的两个版本进行基准测试。但如果测得的差异超过几个百分点,那么基准测试1可能存在缺陷!
我建议不要在这个级别上“优化”,除非你有明确的证据表明:
  1. 代码太慢了,且
  2. 你有明确的证据表明你要优化的代码是导致速度变慢的重要原因之一。
换句话说,先进行基准测试,然后进行性能分析,最后优化值得优化的代码部分。

1 - 在编码之前,建议先了解如何编写正确的微基准测试。可以从这里开始:如何在Java中编写正确的微基准测试?


1
你的第一种方法会创建两个对象 - 新的 Deck 对象和存储卡牌的数组 (由 Deck 构造函数创建的数组)。你的第二种方法将创建 3 个对象 - 新的 Deck,由 Deck 构造函数创建的数组,以及名为 sorted 的数组。
然而,这并不重要,因为你根本没有创建 Card 对象。你只是将两个牌堆中的 Card 对象的引用复制到新的牌堆中!将 Card 赋值给数组并不会创建新的卡牌。就像以下代码不会创建两个对象一样:
Object obj = new Object();
Object obj2 = obj;

实际上这两种方法是相同的。我建议你使用你觉得最易读的那个。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接