gnodet opened a new pull request, #23766: URL: https://github.com/apache/camel/pull/23766
## Summary Replace the `TreeMap`-based `CaseInsensitiveMap` with a custom hash table implementation, improving the performance of every header access in every Camel route. `CaseInsensitiveMap` is the default headers map for every `Exchange` in Camel. It is the most accessed data structure in the framework — every `message.getHeader()`, `setHeader()`, `removeHeader()`, and header iteration goes through it. ### Before (TreeMap with `CASE_INSENSITIVE_ORDER`) - **O(log n)** for `get`, `put`, `containsKey`, `remove` - String comparisons at every tree node during lookup - Deserialized header keys allocate duplicate `String` objects across exchanges - To get O(1), users needed the `camel-headersmap` dependency (cedarsoftware `java-util`, which uses `ThreadLocal` internally — problematic with virtual threads) ### After (custom hash table) - **O(1)** for `get`, `put`, `containsKey`, `remove` - **Zero allocation on lookups** — case-insensitive hash computed char-by-char with `Character.toLowerCase(Character.toUpperCase(c))`, keys compared with `equalsIgnoreCase()`. No `toLowerCase()` string copies - **Header key deduplication** — well-known `Exchange` header constants (141 keys) are registered at startup; deserialized keys matching a known constant are replaced with the canonical interned reference, reducing memory across exchanges - Entries stored in **insertion order** (deterministic iteration) - Original key case preserved (first-put case wins, same as before) - No external dependencies, no `ThreadLocal` - Eliminates the need for `camel-headersmap` in most cases ### Design The map extends `AbstractMap` and implements its own hash table with separate chaining using parallel arrays (`keys[]`, `values[]`, `chainNext[]`). This gives cache-friendly storage and avoids per-entry object allocation overhead of `HashMap.Node`. The hash function uses the same two-step fold as `String.equalsIgnoreCase()` — `Character.toLowerCase(Character.toUpperCase(c))` — ensuring hash consistency even for Unicode edge cases (e.g., Turkish dotless-ı). `DefaultHeadersMapFactory` registers all `Exchange` string constants at startup via `CaseInsensitiveMap.registerKnownKeys()`. On `put()`, a zero-allocation lookup in the static known-keys table replaces deserialized keys with canonical references. ### Compatibility - The `Map<String, Object>` API is unchanged - `DefaultHeadersMapFactory` and `instanceof CaseInsensitiveMap` checks work as before - No code in the codebase uses `SortedMap`/`NavigableMap` methods on this map - Iteration order changes from alphabetical (TreeMap) to insertion order — no code depends on alphabetical ordering - All existing tests pass; 10 new tests added ## Test plan - [x] `CaseInsensitiveMapTest` — 32 tests (+ 10 new: insertion order, iterator removal, entry setValue, entrySet remove, remove-then-reput, resize/rehash, containsValue, null values, clear-reuse, known key deduplication) - [x] `DefaultMessageHeaderTest` — 16 tests - [x] Formatter and import sort clean -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
