【问题标题】:Java For Each with a getter [duplicate]Java For Each 带有一个吸气剂 [重复]
【发布时间】:2017-01-02 04:12:16
【问题描述】:

自从我上次使用 Java 以来已经有一段时间了,因为我主要是 C# 开发人员。为了回到游戏中,我正在开发一个非常简单的应用程序来触及该语言的大部分关键特性。我遇到了以下问题:

for (Player player : teamRed.getPlayers()) {
    System.out.format("> %s\n", player.getName());
}

其中getPlayers()定义如下:

public Iterable<Player> getPlayers() {
    return Collections.unmodifiableList(this.players);
}

在过去的某个时候,当您像这样在 for each 中使用 getter 时,C# 或 Java 都会出现性能问题,因为它会在每次迭代时执行该方法。我再也找不到关于这个的任何东西了,所以我想知道:

Java 有没有遇到过这个问题,还是只有 C# 才有这种情况?

就个人而言,我觉得编译器应该足够聪明,可以正确优化它,并在迭代之前将getPlayers 的结果实际存储在一个临时变量中。但如果没有,我可以毫不费力地帮助编译器:P

【问题讨论】:

  • 查找增强的for语句in the language spec,查找“增强的for语句相当于表单的基本for语句”。你会发现getPlayers() 方法只被调用一次,按照规范。
  • 我不同意这是重复的。我记得它与使用一种方法来检索要迭代的列表特别相关。链接的问题使用对已定义数组的直接访问。
  • 我不记得 Java 曾经遇到过这样的问题(从 1.2 之前开始),而且我很难相信 C# 也会遭受这样的基本疏忽。
  • @LennardFonteijn 这就是为什么它说可能重复:)
  • 请注意,将this.players 包装在不可修改的列表中大多是多余的:它只是意味着无法通过返回的引用修改列表 - 但它可以通过任何持有对列表的引用的东西直接,就像拥有玩家列表的实例一样。你也可以直接返回列表——返回类型是Iterable,它本身是不可修改的。 (或返回列表的副本)。

标签: java c# performance for-loop


【解决方案1】:

编译器将存储它循环的迭代器(通过调用Iterable 上的iterator() 方法),因此getPlayers() 方法只会被调用一次。您可以使用getPlayers()的以下改编来观察这一点

public Iterable<Player> getPlayers() {
    System.out.println("getPlayers() called");
    return Collections.unmodifiableList(this.players);
}

在运行您的第一个代码 sn-p 时,“getPlayers() called”只会打印一次。

查看Iterable 文档了解更多详细信息(尤其是iterator() 方法):https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html

【讨论】:

  • 非常简单而有效。您的“输出”中确实有错字,但不允许我只编辑一个字符:P 也感谢所有其他 cmets。
  • 感谢您让我知道错别字
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-30
  • 2018-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多