cd /news/developer-tools/new-open-source-java-data-library · home › topics › developer-tools › article
[ARTICLE · art-165588] src=github.com ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

New open source Java Data Library

CupOfTea Labs released CupOfTea 0.24.0, an open source Java data manipulation library that provides DataFrame-style filtering, aggregation, joins, and statistical operations on a columnar engine using primitive arrays and BitSet null bitmasks. The library requires Java 17 LTS or later and Maven 3.8+ or Gradle 7+, and ships as a modular set of artifacts — cupoftea-core plus optional CSV, JSON, Excel, Parquet, Arrow, Plot, SQL, HTML, YAML, and XML format modules, or the cupoftea-all aggregator. CupOfTea 0.24.0 adds a first-class Schema definition, an NA missing-value model distinct from empty strings, BigDecimal decimal arithmetic, O(n) quantiles and median via Introselect, rolling and expanding windows, and direct mapping to Java Records and POJOs.

read7 min views1 publishedNov 6, 2026
New open source Java Data Library
Image: Michielbdejong (auto-discovered)

CupOfTea is a lightweight library for data manipulation in Java. It provides a simple and efficient API to work with large structured datasets, enabling operations such as filtering, aggregation, joining, and data analysis.

  • Create DataFrames from arrays, lists, CSV files, and other sources.
  • First-class Schema definition:Schema.of("year", INT, "price", DOUBLE) .
  • Optional automatic type inference on CSV, JSON, and Excel ingest.
  • First-class missing-value model (NA ) distinct from empty strings ("" ).
  • Full support for java.time (LocalDate ,LocalDateTime ,Instant ).
  • Exact currency arithmetic using BigDecimal (Schema.DECIMAL ).
  • Column selection, row filtering, grouping, aggregation, and slicing operations.
  • Relational joins: innerJoin ,leftJoin ,rightJoin ,outerJoin ,crossJoin with automatic column deduplication, multi-key support, and customizable suffixes.

Statistical Operations & Summary : High-performance linear$O(n)$ quantiles and median (via Introselect), sample and population variance and standard deviation, skewness, kurtosis, covariance, correlation matrix (corr() ), and descriptive summary (describe() ). #

Window, Rolling & Cumulative Functions : Sliding rolling windows (df.rolling(w) ), expanding windows (df.expanding() ), cumulative operations (cumsum ,cumprod ,cummin ,cummax ), time series shifts (lead ,lag ,diff ,pctChange ), and SQL-like analytical window partitioning and ranking (df.window().partitionBy(...).orderBy(...).rank() ).

  • Read and write CSV, JSON, Excel, Parquet, and YAML files.

DTO & Record Mapping : Import and export standard Java POJOs/JavaBeans and Java Records directly (CupOfTea.read().records(...) ,df.write().records(...) ,CupOfTea.read().dtos(...) ,df.write().dtos(...) ). #

Columnar Engine : High-performance contiguous memory layout (ColumnVector with primitiveint[] ,double[] ,long[] ,float[] ,boolean[] ,String[] , andBitSet null bitmasks), eliminating per-cell boxed object overhead and row hash lookups. #

Unified Mutation Modes : FluentIN_PLACE builder by default with opt-inCOPY_ON_WRITE via.asCopyOnWrite() and.asInPlace() . #

Deep Copy : Explicit.copy() deep-copy method onCupOfTea andIDataFrame . #

Immutable Row API : Strongly-typed, unmodifiableRow objects with typed accessors (getInt ,getString ,getDouble ,getBoolean ,getLocalDate , etc.) and zero leaking of internal mutable row maps.

  • Java : Java 17 LTS or later
  • Build tool : Maven 3.8+ or Gradle 7+

CupOfTea is modular. You can import only the core engine and whichever IO format modules your project needs, or include cupoftea-all for full format support.

Add the core dependency to your pom.xml:

<dependency>
    <groupId>io.github.cupoftea-labs</groupId>
    <artifactId>cupoftea-core</artifactId>
    <version>0.24.0</version>
</dependency>

Add optional format modules as needed (CSV, JSON, Excel, Parquet, Arrow, Plot, SQL, HTML, YAML, XML):

<!-- Example: Add CSV and JSON format support -->
<dependency>
    <groupId>io.github.cupoftea-labs</groupId>
    <artifactId>cupoftea-csv</artifactId>
    <version>0.24.0</version>
</dependency>
<dependency>
    <groupId>io.github.cupoftea-labs</groupId>
    <artifactId>cupoftea-json</artifactId>
    <version>0.24.0</version>
</dependency>

<!-- Or import all formats with the aggregator module: -->
<!--
<dependency>
    <groupId>io.github.cupoftea-labs</groupId>
    <artifactId>cupoftea-all</artifactId>
    <version>0.24.0</version>
</dependency>
-->

For more details on releases and publishing, see docs/community/releasing.md.

Groovy DSL (build.gradle):

// Core library
implementation 'io.github.cupoftea-labs:cupoftea-core:0.24.0'

// Optional format modules
implementation 'io.github.cupoftea-labs:cupoftea-csv:0.24.0'
implementation 'io.github.cupoftea-labs:cupoftea-json:0.24.0'

// Or all formats at once:
// implementation 'io.github.cupoftea-labs:cupoftea-all:0.24.0'

Kotlin DSL (build.gradle.kts):

// Core library
implementation("io.github.cupoftea-labs:cupoftea-core:0.24.0")

// Optional format modules
implementation("io.github.cupoftea-labs:cupoftea-csv:0.24.0")
implementation("io.github.cupoftea-labs:cupoftea-json:0.24.0")

// Or all formats at once:
// implementation("io.github.cupoftea-labs:cupoftea-all:0.24.0")
Module Description Dependencies / Formats
cupoftea-core Core DataFrame engine, filtering, aggregation, SPI interfaces Zero heavy external deps
cupoftea-csv CSV format reader and writer OpenCSV
cupoftea-json JSON format reader and writer Jackson Databind
cupoftea-excel Excel format reader (.xlsx / .xls) Apache POI 5.5.1
cupoftea-parquet Parquet format reader and writer Apache Parquet / Hadoop
cupoftea-arrow Apache Arrow IPC and Feather zero-copy format reader and writer Apache Arrow Vector & Netty
cupoftea-sql SQL database reader and writer via JDBC with batching and transaction support JDBC ( java.sql ,javax.sql )
cupoftea-html HTML table reader Jsoup
cupoftea-yaml YAML format reader and writer SnakeYAML
cupoftea-xml XML format reader Standard Java XML DOM
cupoftea-plot Declarative plotting engine (Vega-Lite), HTML export, desktop preview Jackson Databind
cupoftea-all Meta-module aggregating all format and plot modules All above formats & plotting

IO formats are dynamically discovered via Service. Ensure the corresponding format module is on your classpath:

import com.cupoftea.CupOfTea;
import com.cupoftea.table.Row;
import com.cupoftea.table.Schema;
import static com.cupoftea.table.Schema.*;
import java.io.File;

public class Main {
    public static void main(String[] args) {
        // Read CSV using fluent API
        CupOfTea df = CupOfTea.read().csv("data.csv");
        df.print();

        // Perform filtering with immutable Row
        CupOfTea filtered = df.filter(row -> row.getInt("age") != null && row.getInt("age") > 30);
        filtered.print();

        // Core pandas-like ops:
        // Selection and dropping of columns (use copy() for independent views)
        CupOfTea selected = df.copy().select("name", "age", "salary");
        CupOfTea withoutDept = df.copy().drop("department");

        // Inspection: head, tail, and slicing
        df.head(5).print();
        df.tail(3).print();
        CupOfTea slice = df.slice(0, 2);

        // Position-based indexing (iloc) with negative index support
        Row lastRow = df.iloc(-1);
        Object cell = df.iloc(0, 1);
        CupOfTea subset = df.iloc().slice(0, 2, 0, 2);

        // Index-based indexing (loc)
        df.setIndex("id");
        Row person = df.loc(101);
        Object name = df.loc(101, "name");

        // Missing value imputation & cleaning (using copy() for branching)
        CupOfTea filled = df.copy().fillna(0);
        CupOfTea cleaned = df.copy().dropna(); // drops rows with any missing value

        // Relational joins
        CupOfTea depts = CupOfTea.read().csv("departments.csv");
        CupOfTea joined = df.innerJoin(depts, "department");
        // Or left, right, outer, cross joins:
        // CupOfTea left = df.leftJoin(depts, "department");
        // CupOfTea cross = df.crossJoin(depts);

        // DataFrame concatenation (vertical / rows or horizontal / columns)
        CupOfTea moreData = CupOfTea.read().csv("more_data.csv");
        CupOfTea stacked = df.concat(moreData); // or CupOfTea.concat(df, moreData)

        // Write to multiple formats
        filtered.write().csv("filtered.csv");
        filtered.write().json("filtered.json");

        // Or switch to COPY_ON_WRITE for immutable transformation chains
        CupOfTea cowDf = df.copy().asCopyOnWrite();
        CupOfTea withoutSalary = cowDf.removeColumn("salary");
    }
}

Format-specific options can also be configured:

// Read CSV with custom separator
CupOfTea df = CupOfTea.read().option("separator", ";").csv(new File("data.csv"));

CupOfTea provides specialized, fluent columnar expressions for string manipulation and date/time feature engineering:

// Vectorized text manipulation
df.withColumn("name_upper", df.col("name").str.toUpperCase());
df.transformColumn("name", df.col("name").str.trim().capitalize());

// Check prefix, suffix, and containment (returns BooleanColumnVector)
BooleanColumnVector isEng = df.col("department").str.startsWith("Eng");

// Vectorized temporal operations
df.withColumn("hire_year", df.col("hire_date").dt.year());
df.withColumn("days_since", df.col("hire_date").dt.daysBetween(LocalDate.now()));
df.transformColumn("hire_date", df.col("hire_date").dt.plusMonths(6));

CupOfTea provides a declarative plotting API (df.plot()) backed by Vega-Lite specifications, producing standalone responsive HTML charts with zero heavy external GUI or native dependencies:

CupOfTea df = CupOfTea.read().csv("data.csv");

// Scatter plot with title, custom labels and desktop preview
df.plot().scatter("experience", "salary")
        .title("Salary vs Experience")
        .show();

// Histogram with custom binning
df.plot().hist("age", 20).show();

// Grouped bar chart saved to standalone interactive HTML file
df.plot().bar("department", "headcount").saveHtml("chart.html");

// Box plot comparing salary distributions across departments
df.plot().box("department", "salary").show();

// Line chart, area chart, and 2D heatmap matrix
df.plot().line("year", "revenue").show();
df.plot().area("date", "active_users").show();
df.plot().heatmap("department", "job_level", "headcount").show();

Interactive HTML Table (df.toHtml()) : Renders responsive HTML with sticky column headers, data type indicators, and client-side pagination:

String html = df.toHtml(); // Default pagination with 25 rows per page
String fullDoc = df.toHtml(TableHtmlConfiguration.builder().pageSize(50).fullDocument(true).build());

Seamless Jupyter / IJava Cell Rendering :CupOfTea ,IDataFrame , andChart objects implement the standard notebook MIME rendering contract (renderHtml() andrender() returningtext/html ). When a DataFrame or chart expression is evaluated in a Jupyter cell (via IJava or Polyglot Notebooks), it renders natively and interactively inside the cell output area.

CupOfTea supports multi-threaded parallel execution across row filtering, column mapping, whole-DataFrame aggregations, and GroupBy operations using vectorized chunking and prefix-sum scans:

// Switch to parallel execution mode (using ForkJoinPool.commonPool())
CupOfTea parDf = df.asParallel();

// Custom thread pool and parallel threshold
ExecutorService customPool = Executors.newFixedThreadPool(8);
df.parallel(customPool).withParallelThreshold(50_000);

// Parallel filtering with zero-copy vectorized chunking
CupOfTea filtered = parDf.filter(row -> row.getDouble("salary") > 80_000.0);

// Parallel column transformations
parDf.mapDouble("salary", s -> s * 1.10);

// Parallel whole-DataFrame aggregations
Object totalRevenue = parDf.sumOf("revenue");
Double avgScore = parDf.meanOf("score");

// Parallel chunk-partitioned GroupBy aggregations
CupOfTea summary = parDf.groupBy("department").agg(
    Aggregations.sum("salary"),
    Aggregations.mean("experience"),
    Aggregations.count("employee_id")
);

// Switch back to sequential single-threaded execution
CupOfTea seqDf = parDf.asSequential();
  • Window and rolling functions.
  • Time series resampling and frequency conversion.

Contributions are welcome! To contribute, follow these steps:

  1. Fork the repository.
  2. Create a branch for your feature (git checkout -b my-feature ).
  3. Commit your changes (git commit -m 'Add new feature' ).
  4. Push to the branch (git push origin my-feature ).
  5. Open a pull request.

This project is licensed under the Apache License, Version 2.0. See the LICENSE file for the full license text.

── more in #developer-tools 4 stories · sorted by recency
── more on @cupoftea labs 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/new-open-source-java…] indexed:0 read:7min 2026-11-06 · —