【问题标题】:Is if statement in for loop faster than one by one if statements in Java?for 循环中的 if 语句是否比 Java 中的一个一个 if 语句更快?
【发布时间】:2023-03-10 09:26:01
【问题描述】:

我想知道如果我使用HashMap来收集条件并循环每个if语句,我是否可以达到更高的性能而不是一个一个地编写if-else if语句?

在我看来,一对一的 if-else, if 语句可能会更快,因为在 for 循环中,每个循环都会运行一个条件,例如,计数器是否达到目标数?所以实际上每个 if 语句,它运行 2 个 if 语句。当然内部语句不同,但如果我们只讨论语句性能,我认为一对一类型会更好?

编辑:这只是一个示例代码,我的问题是关于这些语句的用法之间的性能差异。

Map<String, Integer> words = new HashMap<String, Integer>
String letter ="d";
int n = 4;
words.put("a",1);
words.put("b",2);
words.put("c",3);
words.put("d",4);
words.put("e",5);

words.forEach((word,number)->{
if(letter.equals(word){
System.out.println(number*n);
});

String letter ="d";
int n = 4;
if(letter.equals("a"){
System.out.println(number*1);
}else if(letter.equals("b"){
System.out.println(number*2);
}else if(letter.equals("c"){
System.out.println(number*3);
}else if(letter.equals("d"){
System.out.println(number*4);
}else if(letter.equals("e"){
System.out.println(number*5);
}

【问题讨论】:

  • 您需要展示您的代码以更好地解释您的意思。您是否在任何条件下使用短路或在满足条件时断开?
  • 您很可能将时间浪费在毫无意义的微优化上。 Java 速度来自于 jit 将字节码翻译成机器码。你在这个级别上在 Java 源代码中所做的事情几乎是零影响。编写简单易读和易于理解的代码。并提示:jit 非常擅长将简单的代码翻译成快速的机器指令。
  • @GhostCat 微优化通常毫无意义,但并非总是如此。不应该将任何希望进行微优化的人自动阻止这样做的信念视为一种信条。虽然编译器确实可以进行令人难以置信的优化,但它肯定会根据您在许多情况下编写的代码进行不同的优化。所以你写什么代码很重要。
  • OP“在我看来”你(和我)的意见不值得写在纸上。测量。
  • @mypetlion 因此我说“最有可能”。正如预期的那样,OP 显示了包含打印语句的代码。这告诉我们,他没有真正的性能问题,而是一个想象的问题。衡量这里提供的代码甚至没有意义。

标签: java performance for-loop if-statement hashmap


【解决方案1】:

对于您的示例,拥有一个 HashMap 但随后进行迭代查找似乎不是一个好主意。使用 HashMap 的目的是能够进行基于哈希的查找。这比进行迭代查找要快得多。

此外,从您的示例来看,级联 if-then 测试肯定会更快,因为它们将避免映射迭代器的开销和额外的函数调用。此外,它们将避免映射迭代器跳过哈希映射支持数组中的空存储位置的开销。一个更好的问题是级联 if-then 是否比遍历简单列表更快。这很难回答。级联 if-thens 似乎可能更快,但如果有很多 if-thens,则应该增加加载代码的成本。

对于字符串查找,列表数据结构提供了足够的行为,直到一个限制值,在此之上必须使用更复杂的数据结构。什么是极限值取决于环境。对于字符串比较,我发现了 20 到 100 个元素之间的过渡。

对于特定的查找,以及是否有低级优化可用,转换值可能要大得多。例如,使用“C”进行整数查找,可以直接进行内存查找,转换值要高得多。

典型的数据结构是 HashMap、Tries 和排序数组。每个都适合特定的访问模式。例如,排序数组最快、最紧凑,但更新成本很高。 HashMaps 支持动态更新,并且对于良好的散列函数,提供恒定时间查找。但是,HashMap 的空间效率很低,因为它们依赖于哈希值之间的空单元格。

对于不涉及“非常大”数据集并且不在关键“热”代码路径中的情况,HashMaps 是常用的结构。

【讨论】:

  • 感谢您的意见。我绝对同意你的看法。
【解决方案2】:

如果你有一个 Map 并且你想检索一个字母,我不知道你为什么要循环?

Map<String, Integer> words = new HashMap<String, Integer>
String letter ="d";
int n = 4;
words.put("a",1);
words.put("b",2);
words.put("c",3);
words.put("d",4);
words.put("e",5);

if (words.containsKey(letter) {
  System.out.println(words.get(letter)*n);
}
else
{
  System.out.println(letter + " doesn't exist in Map");
}

如果您没有使用地图的好处,那为什么还要使用地图呢?

forEach 实际上会触及列表中的每个键。检查 if/else 的次数取决于它在列表中的位置以及可用字母列表的长度。如果您选择的字母是列表中的最后一个,那么它将在打印前完成所有检查。如果它是第一个,那么它只会做一个比检查所有要快得多的。

编写这两个示例并运行计时器以确定哪个实际上更快是很容易的。 https://www.baeldung.com/java-measure-elapsed-time

如果您必须运行 100 万个 if/else 语句并且只选择一个可能在列表中的任何位置的语句,那么会有很多浪费的计算。这不包括拼写错误和代码维护的恐惧。使用带有索引的 Map 会快得多。如果您只谈论 100 个 if/else 语句(在我看来仍然太多),那么您可能能够在速度上实现收支平衡。

【讨论】:

  • 不要访问地图两次:Integer result = words.get(letter); if (result!=null) { System.out.println(result*n); } .....
  • @JorgeCampos 有效点。无论如何,我不应该在检查 containsKey() 中访问它。
  • 我只是以这段代码为例。我说的是语句与循环性能。您可能不知道接收到的数据,并且您可能在循环中有不同的条件。
  • 如果您寻求帮助,您应该发布您将使用的代码。 codereview.stackexchange.com 是审查代码和性能的好网站。如果您未按预期使用 HashMap 并且 If/Else 正确,那么我想您可以使其具有更高或更低的性能。一个可能有益的问题是Why am I typing the same thing over and over again?。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-03
  • 2014-02-20
  • 2021-04-13
  • 1970-01-01
  • 2019-05-04
  • 2016-06-16
相关资源
最近更新 更多