【问题标题】:java - fastest way to iterate through List<Map> and compare contents of Map to known datajava - 迭代 List<Map> 并将 Map 的内容与已知数据进行比较的最快方法
【发布时间】:2018-11-06 00:43:32
【问题描述】:

我有一个将在云应用服务器上运行的小型 java 类,因此它需要尽可能快地执行。

我需要做的是遍历List&lt;Map&gt;,获取当前Map 的内容,然后对其进行一些逻辑处理。 Map 包含字符串和双精度数。

这是我当前的实现:

for (int i = 0; i < count; i++) {

  Map data = result.get(i);
  double priceToCheck = Double.parseDouble(data.get("value").toString());
  String criteria = data.get("criteria").toString();
  String coin = data.get("coin").toString();


  if (coin.equals("BTC")) {
    if (criteria.equals("above")) {
      if (BTC > priceToCheck) {
        // create notficaition
        sendNotification = true;

      }
    } else {
      if (BTC < priceToCheck) {
        // create notification
        sendNotification = true;
      }
    }
  } else if (coin.equals("BCH")) {
    if (criteria.equals("above")) {
      if (BCH > priceToCheck) {
        // create notficaition
        sendNotification = true;
      }
    } else {
      if (BCH < priceToCheck) {
        // create notification
        sendNotification = true;
      }
    }
  } else if (coin.equals("ETH")) {
    if (criteria.equals("above")) {
      if (ETH > priceToCheck) {
        // create notficaition
        sendNotification = true;
      }
    } else {
      if (ETH < priceToCheck) {
        // create notification
        sendNotification = true;
      }
    }
  } else if (coin.equals("ETC")) {
    if (criteria.equals("above")) {
      if (ETC > priceToCheck) {
        // create notficaition
        sendNotification = true;
      }
    } else {
      if (ETC < priceToCheck) {
        // create notification
        sendNotification = true;
      }
    }
  } else if (coin.equals("LTC")) {
    if (criteria.equals("above")) {
      if (LTC > priceToCheck) {
        // create notficaition
        sendNotification = true;
      }
    } else {
      if (LTC < priceToCheck) {
        // create notification
        sendNotification = true;
      }
    }
  } else if (coin.equals("XRP")) {
    if (criteria.equals("above")) {
      if (XRP > priceToCheck) {
        // create notficaition
        sendNotification = true;
      }
    } else {
      if (XRP < priceToCheck) {
        // create notification
        sendNotification = true;
      }
    }

  }

resultList&lt;Map&gt;"BTC" 是字符串,BTC 是双精度数

您可以看到最高级别的 if 语句检查字符串 coin,有六个可能的值。找到coin 后,我确定criteria 的值,然后根据criteria 的值比较双精度数

我觉得这是一种完成这项任务的非常繁琐的方式,它确实有效,但速度相对较慢。如果不直接访问每个Map 元素并手动检查内容,我想不出一种方法来加快速度。

还有其他人有什么想法吗?

【问题讨论】:

  • 创建一个硬币列表,其中每个硬币都有一个名称和价值。那么内部的 if 块可以折叠成一个循环,覆盖硬币列表。此外,您似乎只设置了一个值“sendNotification”。当你第一次发现这是真的时,你可以打破所有的循环。
  • @jtahlborn 谢谢。我无法跳出循环,因为“结果” List 中可能有多个需要关联通知的对象,因此 break 只会让我找到第一个。硬币也只是字符串值
  • 您是否需要地图列表?您会处理可能包含相同密钥的多个地图吗?例如硬币的名称?恕我直言,您似乎只想要一个要使用地图填充的 POJO 列表。
  • @shinjw 一个 Map 列表是当我使用它的 API 访问它的数据库时从云服务器返回的内容

标签: java arrays if-statement optimization


【解决方案1】:

我有一个将在云应用服务器上运行的小型 java 类,因此它需要尽可能快地执行。

首先,其中有一些值得怀疑的假设。

  1. 是的,让您的代码尽可能快地运行是一件好事,但在大多数情况下,这不是必需的。特别是,您在云服务器上运行这一事实并不一定使其成为必需品。

  2. 您认为您的应用程序运行速度不够快。 (你做过基准测试吗?)

  3. 您假设这部分代码是(或将要)导致代码太慢的原因。 (你实现了吗?你分析了吗?)

还有这个:

我觉得这似乎是完成这项任务的一种非常繁琐的方式,它确实有效,但速度相对较慢。

繁琐和慢是不一样的。通常繁琐的冗长/笨拙比简洁/优雅更快


那么现在来看看您的代码的潜在性能问题。 (请记住,这可能与您的假设不正确无关!)

  1. 如果字段是 / 可以在编译时知道,最好使用自定义类而不是 MapMap::get 方法将比自定义类上的 getter 慢几个数量级,而 Map 通常会使用更多数量级的内存。

    自定义类还允许您使用原始类型等,而不是将值硬塞到String 中。避免这种情况也会带来性能优势。

  2. 这很慢:

    double priceToCheck = Double.parseDouble(data.get("value").toString());
    

    您似乎正在使用double(或Double, converting it to a string and then converting it back to adouble`。数字和十进制字符串之间的转换相对昂贵。

  3. 如果coincriteria 的值在编译时已知,请考虑使用enumboolean 而不是字符串。比较会更快,您将能够使用switch 语句...或在布尔情况下使用简单的if

事实上,通过列表的迭代是优化机会不多的一个方面。

【讨论】:

  • 谢谢。代码将在其上运行的云服务器的执行时间限制为 5 秒。不幸的是,这些字段在编译时是未知的,并且每次执行代码时都会从云服务器上的数据库中读取。这就需要用到Map了,而且map的所有元素都是object,有没有更好的方法从object转换为double?
  • 0) 所以......您需要优化的真正原因是 5 秒的时间限制。 (实际上与“云”无关。任何服务器都可能有时间限制!) 1)如果你真的必须使用Map,那么优化的空间很小。查看您从数据库中读取的方式,看看您是否可以使用自定义类。我希望有。 2) 对象的真实类型是什么?
  • 是的,我会检查是否可以实现自定义类。我使用的 API 为地图中的每个元素返回 java.lang.Object。在服务器端,虽然“值”是双倍
  • 找出客户端的真实类型。它不会是java.lang.Object。我可以保证。
  • 在客户端(swift iOS 应用)“值”是双倍
【解决方案2】:

这里有一个真正突出的优化。您的原始代码片段将遍历您的整个列表以调整您的 sendNotification 布尔值。

如果您只需要设置sendNotification,您可以策略性地将break 放置在您的每个条件中。这将在所需行为之后使循环短路。在最坏的情况下,您最终会遍历整个列表。

for (int i = 0; i < count; i++) {


  if (coin.equals("BTC")) {
    if (criteria.equals("above")) {
      if (BTC > priceToCheck) {
        // create notficaition
        sendNotification = true;
        break; // exits the loop

      }
    } else {
      if (BTC < priceToCheck) {
        // create notification
        sendNotification = true;
        break;
      }
   }
  } else if (coin.equals("BCH")) {
    if (criteria.equals("above")) {
      if (BCH > priceToCheck) {
        // create notficaition
        sendNotification = true;
        break;
      }

【讨论】:

    猜你喜欢
    • 2015-01-07
    • 2020-01-26
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多