{"id":24948966,"url":"https://github.com/lanseqingling/curve-tool","last_synced_at":"2025-03-28T19:17:25.972Z","repository":{"id":278331310,"uuid":"913210844","full_name":"lanseqingling/curve-tool","owner":"lanseqingling","description":"一个基于函数式编程的数据曲线计算工具。","archived":false,"fork":false,"pushed_at":"2025-02-19T07:07:13.000Z","size":10,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-19T08:22:49.795Z","etag":null,"topics":["curve","functional-programming","java","tool"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lanseqingling.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-07T08:44:43.000Z","updated_at":"2025-02-19T07:10:56.000Z","dependencies_parsed_at":"2025-02-19T08:22:50.917Z","dependency_job_id":"18b44f9f-87b5-4d50-8cf4-6283368882b6","html_url":"https://github.com/lanseqingling/curve-tool","commit_stats":null,"previous_names":["lanseqingling/curve-tool"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lanseqingling%2Fcurve-tool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lanseqingling%2Fcurve-tool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lanseqingling%2Fcurve-tool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lanseqingling%2Fcurve-tool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lanseqingling","download_url":"https://codeload.github.com/lanseqingling/curve-tool/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246085644,"owners_count":20721213,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["curve","functional-programming","java","tool"],"created_at":"2025-02-02T21:36:19.817Z","updated_at":"2025-03-28T19:17:25.963Z","avatar_url":"https://github.com/lanseqingling.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Curve-Tool\n\n## 介绍\n\n### 概述\n\nCurve-Tool 是一个简易的数据曲线计算工具，使用函数式编程的方式实现自定义公式计算、多曲线叠加计算、分组计算等，一些场景可提高开发效率，简化代码，使开发者专注核心计算而非维护数据关系。\n\n![](https://fastly.jsdelivr.net/gh/chocohQL/ql-file@main/assets/github/curve2.png)\n\n### 使用场景\n\n+ 轻量级数据可视化，不使用 Prometheus \u0026 Grafana 等专业工具。\n+ 数据曲线的处理计算或不同类型数据曲线的叠加计算。\n+ 关注核心计算，避免大量维护数据关系（如遍历、分组、条件）。\n\n![](https://fastly.jsdelivr.net/gh/chocohQL/ql-file@main/assets/githubQLC-tool-02.png)\n\n### 工具缺陷\n\n+ 多曲线计算需要严格对齐数据，无法应对复杂处理场景。\n+ 大数据量计算效率较低，后续考虑使用 Fork/Join 框架优化。\n+ 大量函数式编程会造成更多调试分析的障碍。\n\n## 快速开始\n\n### 创建曲线\n\nICurve 接口定义了曲线计算方法，它继承了 List 。Curve 类是该接口的通用实现类，它本身是对 ArrayList 的增强。\n\n```java\n@Data\npublic class Data {\n    private Double val;\n    private Long timestamp;\n}\n```\n\n```java\n// 获取数据集\nList\u003cData\u003e data = getData();\n// 创建曲线，ICurve\u003cT, V\u003e 泛型1表示数据本身，泛型2表示用于计算的属性类型\nICurve\u003cData, Double\u003e curve2 = new Curve\u003c\u003e(data);\n```\n\n### 单曲线处理\n\nprocess() 方法针对的是曲线每一个元素，第一个表达式产生结果，第二个表达式对第一个表达式产生的结果进行消费，这样设计实际上是分离了处理和消费的逻辑，因此你可以传递 setter 方法引用对结果赋值，当然也可以自定义其他消费逻辑。\n\n```java\n// 集合中每个数据的 val 属性 x2 后赋值 \ncurve.process(d -\u003e d.getVal() * 2, Data1::setVal);\n// 集合中每个数据的 val 属性 x2 后打印\ncurve.process(d -\u003e d.getVal() * 2, (d, v) -\u003e System.out.println(v));\n```\n\n三个参数的 process() 方法为需要传递条件断言，满足条件的才会执行后续定义的计算逻辑\n\n```java\n// 集合中数据的 val 属性满足 \u003e 0.5 这个条件的 x2 后赋值\ncurve.process(d -\u003e d.getVal() \u003e 0.5, d -\u003e d.getVal() * 2, Data1::setVal)\n```\n\n如果你不想要拆分条件、处理和消费逻辑，那么你也可以直接使用单一参数的 process() 方法，类似于 peek() 方法\n\n```java\ncurve.process(d -\u003e {\n        // TODO ...\n        d.setVal(d.getVal() * 2);\n        // TODO ...\n    });\n```\n\n### 多曲线叠加处理\n\n![](https://fastly.jsdelivr.net/gh/chocohQL/ql-file@main/assets/githubQLC-tool-03.svg)\n\n如果你需要对两条曲线进行叠加处理，并且它们的在曲线集合中的数据一一对应（长度相同、下标对应），那么可以使用 biProcess() 方法，你可以传递不同类型的曲线集合，只需要保证泛型2类型一致（用于计算）。\n\n```java\n@Data\npublic class Data1 {\n    private Double val;\n    private Long timestamp;\n}\n\n@Data\npublic class Data2 {\n    private Double val;\n    private Long timestamp;\n}\n```\n\n```java\n// 获取数据集\nArrayList\u003cData1\u003e data1 = getData1List();\nArrayList\u003cData2\u003e data2 = getData2List();\n// 创建曲线\nICurve\u003cData2, Double\u003e curve2 = new Curve\u003c\u003e(data2);\nICurve\u003cData1, Double\u003e curve1 = new Curve\u003c\u003e(data1);\n\ncurve1\n        // 叠加计算\n        .biProcess(curve2, (d1, d2) -\u003e d1.getVal() + d2.getVal(), Data1::setVal)\n        // 条件叠加计算\n        .biProcess(curve2,\n                (d1, d2) -\u003e 1 \u003c= d1.getVal() * d2.getVal(),\n                (d1, d2) -\u003e d1.getVal() + d2.getVal(),\n                Data1::setVal)\n```\n\n### 创建分组曲线\n\n如果你需要将数据分为多条曲线（分组/维度），且需要对不同组的曲线进行独立的处理，那么可以使用分组曲线，它可以帮你划分数据集隔离执行相同的 ICurve 操作。\n\n![](https://fastly.jsdelivr.net/gh/chocohQL/ql-file@main/assets/githubQLC-tool-06.svg)\n\nICurveGroup 接口继承了 Map ，它有三个泛型，第一个为分组 Key 的类型，后两个与 Curve 一致，CurveGroup 为通用实现类，提供了创建分组曲线的方法，需要传入数据集合和进行分组的规则。需要注意的是分组并不是指一个 key 对应了多条曲线，分组是针对的数据，它实际上是 Map\u003cK, ICurve\u003cT, V\u003e\u003e 的形式，在两个 CurveGroup 进行叠加计算时的分组才是多条曲线。\n\n```java\n@Data\npublic class Data {\n    private Double val;\n    private Long timestamp;\n    private String tag;\n}\n```\n\n```java\nArrayList\u003cData\u003e data = data1();\n// 根据 Data 的 tag 属性进行分组\nICurveGroup\u003cString, Data, Double\u003e curveGroup = CurveGroup.create(data, Data::getTag);\n```\n\n### 分组曲线处理\n\nICurveGroup 的处理逻辑和 ICurve 类似，它会在表达式中多提供一个 key 辅助你的处理，如果是两个分组曲线进行计算，会自动匹配相同分组的两条曲线，于是你可以将他当成普通的 ICurve 处理。\n\n```java\n@Data\npublic class Data1 {\n    private Double val;\n    private Long timestamp;\n    private String tag;\n}\n\n@Data\npublic class Data2 {\n    private Double val;\n    private Long timestamp;\n    private String tag;\n}\n```\n\n```java\ncurveGroup1\n        // 分组计算\n        .process((tag, d) -\u003e d.getVal() + 0.1, Data1::setVal)\n        // 分组条件计算\n        .process((tag, d) -\u003e d.getVal() \u003e 0.5, (tag, d) -\u003e d.getVal() + 0.1, Data1::setVal)\n        // 分组叠加计算\n        .biProcess(curveGroup2, (tag, d1, d2) -\u003e d1.getVal() + d2.getVal(), Data1::setVal)\n        // 分组条件叠加计算\n        .biProcess(curveGroup2,\n                (tag, d1, d2) -\u003e tag.equals(\"tagA\") || d1.getVal() + d2.getVal() \u003e 0.5,\n                (tag, d1, d2) -\u003e d1.getVal() * 2,\n                Data1::setVal)\n```\n\n有时候你也许并不想直接对具体数据进行操作，而是想操作不同分组下的曲线，那么你也可以使用 forCurve 方法调出对应分组的曲线来自定义处理过程。\n\n```java\ncurveGroup1.forCurve((key, curve1) -\u003e {/*TODO*/})\n\ncurveGroup1.forCurve(curveGroup2, (tag, curve1, curve2) -\u003e {\n            curve1.process(d -\u003e{/*TODO*/});\n            curve2.process(d -\u003e{/*TODO*/});\n        });\n```\n\n## 关系图\n\n![](https://fastly.jsdelivr.net/gh/chocohQL/ql-file@main/assets/githubQLC-tool-08.svg)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flanseqingling%2Fcurve-tool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flanseqingling%2Fcurve-tool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flanseqingling%2Fcurve-tool/lists"}