【问题标题】:Best practices for returning multiple values?返回多个值的最佳实践?
【发布时间】:2018-11-01 13:58:36
【问题描述】:

假设我想设计一个返回给定股票信息的函数。该函数接收股票名称作为字符串类型的参数,然后返回几个值。它可能返回的一些值是:

int price
int profitability
double currentTrend
int mostRecentSpike
long timeOfRecentSpike

如您所见,它们都是不同的原始类型。我想知道从优化的角度来看,返回这些值的最佳方法是什么。所以如果我要像这样制作一个自定义对象:

class Stock {
    int price;
    int profitability;
    double currentTrend;
    int mostRecentSpike;
    long timeOfRecentSpike;
    public Stock(int price, int profitability, double currentTrend, int mostRecentSpike, long timeOfRecentSpike) {
        this.price = price;
        this.profitability = profitability;
        this.currentTrend = currentTrend;
        this.mostRecentSpike = mostRecentSpike;
        this.timeOfRecentSpike = timeOfRecentSpike;
    }
}

并返回它,它会比我简单地返回这个的替代方案更好:

new Object[] {price, profitability, currentTrend, mostRecentSpike, timeOfRecentSpike}

然后将所有内容转换为适当的原始类型?虽然我知道返回和强制转换 Object[] 时可读性会降低,但我主要关心的是 CPU、内存和序列化方面的性能。

  • 哪个会更占用 CPU 资源?
  • 哪个会占用更多内存?
  • 哪个最适合与序列化搭配使用?

这个问题只是我实际遇到的一个更大问题的隐喻,只是规模更大,需要更多解释。因此,即使在这个小例子中差异可以忽略不计,但在我的实际情况下,它会扩大到更加显着。

【问题讨论】:

  • “从优化的角度来看” - 为什么?您面临哪些性能问题?
  • CPU 和内存应该差不多(数组是 Java 中的对象,因此它们与您的对象相同)。自定义类最适合序列化,因为您可以给它一个固定的序列化 ID 并覆盖方法以在需要时提供自定义序列化。自定义类对于代码的可读性也更好。
  • 返回Stock,因此字段保留其类型和语义。
  • Fwiw,Google 将AutoValue 广泛用于此目的。
  • “因此,即使在这个小例子中差异可以忽略不计,但在我的实际情况下,它会放大到更加显着。”在Object[] 中返回所有内容的最大问题是您会丢失语义信息。第二个最大的问题是您必须将所有原语装箱,这会给您带来每个数组元素的开销。使用自定义类允许您将事物存储为原语,因此每个返回值只需承担一次开销。

标签: java performance memory optimization memory-management


【解决方案1】:

从优化的角度来看最好的做法是返回一个 Stock 对象,因为强制转换会导致更多的 cpu 和内存使用,甚至可能导致 classCastException 之类的异常,如果在任何情况下你错过任何变量。

所以,

return new Stock(price, profitability, currentTrend, mostRecentSpike, timeOfRecentSpike);

【讨论】:

  • 调试错误类型和数组边界错误所花费的时间会使额外的时间和内存成本相形见绌。
【解决方案2】:

我将把这些 cmets 总结为一个连贯的答案,因为它们回答了我的问题很多。

标记空间:

由于数组是 Java 中的对象,它们将具有与 Stock 自定义类相似的结构,因此需要基本相同数量的内存和 CPU 资源。

从序列化的角度来看,自定义类有一个优势,因为它有一个固定的序列化 ID,如果需要,也可以自定义。

自定义类还提高了可读性。

安迪·特纳:

使用 Object[] 输入的每个值都将成为一个 Object,当您从该数组中检索元素时,您需要将它们从 Object 装箱到它们的非原始对应物(Long、Double、Integer),这有一些开销.使用自定义类,您可以将所有内容存储为原语,因此不需要装箱,因此没有开销。

如果您想在自定义类中使用非原始值,从内存的角度来看,情况会更糟。将字段设为 int 类型的内存效率比将其存储为 Integer 的内存效率高约 4 倍。

【讨论】:

    【解决方案3】:

    当你说

    在我的实际情况下,它会扩大到更加重要的程度。

    我怀疑你实际上没有数据来证明这一点(好像你有,我怀疑你会在这里问......)

    我建议您尽可能以最清晰的方式编写它,这可能涉及传递对实际对象的引用,直到您真正得到数据来证明这是一个真正的问题。 (99% 的时间,“明显”的时间槽不是)

    【讨论】:

      猜你喜欢
      • 2015-09-01
      • 2013-05-12
      • 1970-01-01
      • 2012-02-03
      • 2016-11-23
      • 1970-01-01
      • 1970-01-01
      • 2017-07-23
      • 1970-01-01
      相关资源
      最近更新 更多