J-cube -

"dimensions": ["Time", "Product"], "data": [ "Time.Year": 2025, "Product.Category": "Electronics", "sales": 1200.0, "units": 5 ]

// Insert facts cube.loadFact(new Fact() .dim("Time.Year", 2025) .dim("Product.Category", "Electronics") .measure("sales", 1200.0) .measure("units", 5)); j-cube

Example code and binary releases at https://github.com/example/j-cube (hypothetical). "dimensions": ["Time", "Product"], "data": [ "Time

// Query: slice Year=2025, roll‑up Product to Category Result result = cube.query() .slice("Time.Year", 2025) .rollUp("Product", "Category") .execute(); 4.1 In‑Memory Storage A HashMap<KeyTuple, Cell> where KeyTuple encodes dimension coordinates. Lookup is O(1) for point queries; range queries use linear scan over keys – acceptable for cubes < 10⁶ cells. 4.2 Aggregation with Memoization Roll‑up operations pre‑compute aggregates lazily. First query triggers aggregation and caches results; subsequent identical roll‑ups return instantly. 4.3 JSON Serialization Using javax.json , cubes export to: 000 facts (4 dimensions

| Operation | Time (ms) | Memory (MB) | |------------------|-----------|-------------| | Load facts | 680 | 145 | | Slice (equality) | 12 | – | | Dice (3 filters) | 54 | – | | Roll‑up (2 levels)| 210 | 78 (cache) | | Full cube export | 340 | – |

Tests on a synthetic dataset of 500,000 facts (4 dimensions, 2 measures):