【问题标题】:Efficient formula binding at runtime运行时高效的公式绑定
【发布时间】:2012-12-26 04:40:09
【问题描述】:

我的 UI 的一个元素是一个表格,其中显示了按类别聚合的项目列表,并带有一些公式(请参阅下面的目标输出)。

允许用户将单元格绑定到类似电子表格的公式的最佳方法是什么?

  • 性能:实际数据变化频繁,表可能很大,公式很复杂,因此性能和 CPU 使用率是一个问题。
  • 易于配置(假设配置由开发人员完成,因此可能涉及编程)
  • 配置的可维护性

到目前为止我设想的方法:

  1. 使用 Java Scripting API,但我宁愿坚持使用基于 JVM 的方法以获得更好的性能
  2. 创建一个interface Formula { double calculate(); } 并在运行时生成、编译和加载实现 - 允许 JIT 编译生成的方法
  3. 与 2 相同,但使用另一种基于 JVM 的语言,例如 clojure,它可以轻松进行动态编译并具有非常适合的功能方法(例如,map/reduce 将有助于下面的平均值和总和计算) - 但不确定性能影响。

哪种方法更有意义?还有其他我应该考虑的解决方案或库吗?


示例

为了使目标更清晰,这里是一个人为的例子 - 让我们假设表中的项目是:

public class Item() {
    public String category;
    public String name;
    public int quantity;
    public double price;
}

目标输出

Category     Name        Quantity    Price (avg)     Value (sum)
All                                      82            1,090

Bikes                                    45              650
             Bike 1         10           40              400
             Bike 2          5           50              250

Cars                                    120              440
             Car 1           3          100              300
             Car 2           1          140              140

列配置

列可以这样定义:

Column #      Formula
    1         item.name;
    2         item.quantity;
    3         item.price;
    4         Math.abs(column_2 * column_3); //calls a JDK method

聚合配置

聚合类别和汇总公式可以这样定义:

AGGREGATION #1: Category cat = item.category();
Column #      Formula
    1         cat;
    2         "";
    3         thisColumn.filter(cat).items().average(); //utility method
    //this one is more complex
    4         { double sum = 0;
                for (double value : thisColumn.filter(cat).items())
                    sum += value;
                return sum;
              }

【问题讨论】:

  • 可以选择 Java 8 吗?否则,您可以使用普通的旧反射。
  • @PeterLawrey Java 8 还没有不幸。解析公式并通过反射调用相关成员/方法时的普通反射?
  • 是的。对于 JITed 代码,获取字段可能需要

标签: java runtime formula jvm-languages


【解决方案1】:

我将使用您的用户可以使用的自定义域特定语言,并让 ANTLR 在 java 中生成一个本机解析器,将表达式解析为可执行函数。

参见例如http://arcanecoder.blogspot.be/2008/04/using-antlr-to-create-excel-like.html 是一个类似的例子,http://www.antlr.org/wiki/display/ANTLR3/Expression+evaluator 是最近的例子。

您可以定义“sum”、“average”等函数并将其映射到自定义 java 代码,并使用例如$1 或 ${name} 让它们引用属性。

您只定义您希望用户使用的那些函数,因此他们不能使用任何在通用脚本语言中可用的有害函数。

【讨论】:

  • 这意味着我需要定义和维护语法、函数等。我可以忍受与访问整个 JDK 相关的安全问题,这将使我的生活更简单:阅读代码(其中是Java语法),调用编译器,运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
  • 1970-01-01
  • 2012-02-20
  • 2014-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多