HPPC:

API & Code Examples

HPPC API overview

While HPPC is not strictly modeled after Java Collections Framework (JCF), we did try to make the APIs look similar enough for comfortable use. One particular JCF feature not found in HPPC is collection views, such as sub-lists. These can be easily implemented as decorators over HPPC collections if needed. On the other hand, HPPC collections offer a number of additional performance-oriented methods not found in JCF, please see code samples for an overview.

HPPC collections come in two flavours: for primitives and with generics. Technically, the primitive collections are automatically generated based on the generic ones. While HPPC is mainly about primitives, we also distribute the generic-based collections, so that the benefits of direct data store access are also available for collections of non-primitives.

Relationships between HPPC and Java Collections.
Java Collections HPPC (primitives) HPPC (generics)
bit sets BitSet BitSet n/a
array-backed lists ArrayList, Vector [type]ArrayList ObjectArrayList<T>
stacks Stack [type]Stack ObjectStack<T>
deques ArrayDeque [type]ArrayDeque ObjectArrayDeque<T>
hash maps HashMap [keyType][valueType]OpenHashMap ObjectObjectOpenHashMap<K, V>
[keyType]ObjectOpenHashMap<V>
Object[valueType]OpenHashMap<K>

The method-level API of the corresponding types is also similar to Java Collections, but distinct differences exist. Please consult the JavaDoc of a specific class for details.

Example code

Below are some code snippets for the most common programming tasks in which HPPC is likely to be helpful. Certain goals can be achieved in a number of different ways resulting in different performance and code maintainability.

While we try to indicate which variant is likely to be the fastest, your results may vary based on many different factors, including: runtime platform, JVM, structure of your code. Therefore, micro-benchmark your actual application on the target JVM, operating system and hardware to get accurate performance predictions (JUnitBenchmarks may come in handy!).

Iterating

There are three common patterns for iterating over all HPPC collections: using an iterator, with closure-like procedures and by accessing the internal storage buffers. The latter will most likely be the fastest, at the price of code elegance and dependency on HPPC internals.

Iterating over lists

Below are the three common and one list-specific iteration patterns. We present them in the order of performance, from the slowest (but most elegant one) to the fastest one.

Iterating over deques

Iterating over deques (double ended queues) is similar to iterating over lists with an addition of last-to-first iteration.

Iterating over sets

Iterating over sets is in principle the same as for lists, the only major difference is iterating using direct buffer access shown below.

Iterating over maps

Iterating over maps is similar to lists, the only difference is that the cursors are now [keyType][valueType]Cursor and procedures are [keyType][valueType]Procedure.

Collecting values from closures

Pseudo-closures (anonymous class instances) are a convenient way to iterate over all values of a given container (list, set or map). Java imposes several restrictions on passing values to and from such anonymous types (in general, only constant values can be passed to the anonymous class's object via synthetic methods or constructors). Starting from version 0.3.2 of HPPC, forEach method will return the argument type it receives, which makes it possible to access any methods or fields of that type (even if it is anonymous). An example of applying this feature is shown below to count map items with value larger than 10.

Counting character bigram occurrences

A bigram is a pair of characters. Counting bigram occurrences in strings is a very common text processing task. It can be easily accomplished with an int to int map:

        // Some character data
        final char [] CHARS = DATA;
        
        /* 
         * We'll use a int -> int map for counting. A bigram can be encoded
         * as an int by shifting one of the bigram's characters by 16 bits
         * and then ORing the other character to form a 32-bit int.
         */ 
        final IntIntOpenHashMap counts = new IntIntOpenHashMap(
            IntIntOpenHashMap.DEFAULT_CAPACITY, 
            IntIntOpenHashMap.DEFAULT_LOAD_FACTOR);

        for (int i = 0; i < CHARS.length - 1; i++)
        {
            counts.putOrAdd((CHARS[i] << 16 | CHARS[i+1]), 1, 1);
        }

Coding tips

A few things worth doing when using HPPC: