CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-it-unimi-dsi--fastutil

High-performance type-specific collections extending the Java Collections Framework with memory-efficient primitive containers and big data structures.

Pending
Overview
Eval results
Files

priority-queues-stacks.mddocs/

Priority Queues and Stacks

Specialized priority queue implementations including indirect priority queues and stack interfaces with enhanced functionality beyond standard Java collections.

Overview

FastUtil provides several types of priority-based data structures:

  • Priority Queues: Standard priority queues with enqueue/dequeue operations
  • Indirect Priority Queues: Priority queues that operate on indices rather than elements directly
  • Stacks: Stack interfaces with optional enhanced functionality like peeking at arbitrary depths
  • Utility Classes: Helper classes for creating synchronized wrappers and other queue operations

These implementations focus on performance and provide additional functionality not available in standard Java collections.

Capabilities

Priority Queue Interface

Standard priority queue interface with enqueue/dequeue operations and optional bidirectional access.

/**
 * Priority queue with enqueue/dequeue operations
 * @param <K> the type of elements
 */
public interface PriorityQueue<K> {
    /**
     * Add element to the queue
     * @param x the element to add
     */
    void enqueue(K x);
    
    /**
     * Remove and return the first (highest priority) element
     * @return the first element
     * @throws NoSuchElementException if queue is empty
     */
    K dequeue();
    
    /**
     * Get the first (highest priority) element without removing it
     * @return the first element
     * @throws NoSuchElementException if queue is empty
     */
    K first();
    
    /**
     * Get the last (lowest priority) element without removing it (optional operation)
     * @return the last element
     * @throws NoSuchElementException if queue is empty
     * @throws UnsupportedOperationException if not supported
     */
    K last();
    
    /**
     * Notify that the first element has been changed externally (optional operation)
     * This method should be called after modifying the first element in place
     * @throws UnsupportedOperationException if not supported
     */
    void changed();
    
    /**
     * Test if the queue is empty
     * @return true if the queue contains no elements
     */
    boolean isEmpty();
    
    /**
     * Get the number of elements in the queue
     * @return the number of elements
     */
    int size();
    
    /**
     * Remove all elements from the queue
     */
    void clear();
    
    /**
     * Get the comparator used to order elements
     * @return the comparator, or null if natural ordering is used
     */
    Comparator<? super K> comparator();
}

Usage Examples:

import it.unimi.dsi.fastutil.objects.*;
import java.util.Comparator;

// Create priority queue with natural ordering
ObjectHeapPriorityQueue<String> queue = new ObjectHeapPriorityQueue<>();
queue.enqueue("zebra");
queue.enqueue("apple");
queue.enqueue("banana");

// Dequeue in sorted order
while (!queue.isEmpty()) {
    String item = queue.dequeue();
    System.out.println(item); // apple, banana, zebra
}

// Priority queue with custom comparator (reverse order)
ObjectHeapPriorityQueue<Integer> numbers = new ObjectHeapPriorityQueue<>(
    Comparator.reverseOrder());
numbers.enqueue(5);
numbers.enqueue(2);
numbers.enqueue(8);

System.out.println(numbers.first()); // 8 (highest number first)
System.out.println(numbers.last());  // 2 (lowest number last)

Indirect Priority Queue Interface

Priority queue that operates on integer indices rather than elements directly, useful when elements are stored separately.

/**
 * Priority queue operating on indices instead of elements directly
 * Elements are stored separately and referenced by integer indices
 */
public interface IndirectPriorityQueue {
    /**
     * Add index to the queue
     * @param x the index to add
     */
    void enqueue(int x);
    
    /**
     * Remove and return the first (highest priority) index
     * @return the first index
     * @throws NoSuchElementException if queue is empty
     */
    int dequeue();
    
    /**
     * Get the first (highest priority) index without removing it
     * @return the first index
     * @throws NoSuchElementException if queue is empty
     */
    int first();
    
    /**
     * Get the last (lowest priority) index without removing it (optional operation)
     * @return the last index
     * @throws NoSuchElementException if queue is empty
     * @throws UnsupportedOperationException if not supported
     */
    int last();
    
    /**
     * Notify that the first element has been changed externally (optional operation)
     * @throws UnsupportedOperationException if not supported
     */
    void changed();
    
    /**
     * Notify that the element at specified index has been changed (optional operation)
     * @param i the index of the changed element
     * @throws UnsupportedOperationException if not supported
     */
    void changed(int i);
    
    /**
     * Notify that all elements have been changed externally (optional operation)
     * @throws UnsupportedOperationException if not supported
     */
    void allChanged();
    
    /**
     * Test if the queue contains the specified index
     * @param index the index to test
     * @return true if the index is in the queue
     */
    boolean contains(int index);
    
    /**
     * Remove specific index from the queue
     * @param index the index to remove
     * @return the position of the removed index in the queue
     * @throws NoSuchElementException if index is not in queue
     */
    int remove(int index);
    
    /**
     * Test if the queue is empty
     * @return true if the queue contains no indices
     */
    boolean isEmpty();
    
    /**
     * Get the number of indices in the queue
     * @return the number of indices
     */
    int size();
    
    /**
     * Remove all indices from the queue
     */
    void clear();
    
    /**
     * Get the comparator used to order elements by index
     * @return the comparator used for element comparison
     */
    Comparator<?> comparator();
}

Usage Examples:

import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.objects.*;

// Separate storage for elements
String[] elements = {"zebra", "apple", "banana", "cherry"};

// Indirect priority queue orders indices based on element values
IndirectPriorityQueue queue = new ObjectHeapIndirectPriorityQueue<>(
    elements, String::compareTo);

// Add indices to queue
queue.enqueue(0); // "zebra"
queue.enqueue(1); // "apple"  
queue.enqueue(2); // "banana"
queue.enqueue(3); // "cherry"

// Dequeue indices in order of element priority
while (!queue.isEmpty()) {
    int index = queue.dequeue();
    System.out.println("Index " + index + ": " + elements[index]);
    // Index 1: apple
    // Index 2: banana  
    // Index 3: cherry
    // Index 0: zebra
}

// Modify element and notify queue
elements[1] = "aardvark"; // Change "apple" to "aardvark"
if (queue.contains(1)) {
    queue.changed(1); // Notify that element at index 1 changed
}

Stack Interface

Stack interface with push/pop operations and optional enhanced functionality.

/**
 * Stack with push/pop operations and optional peeking
 * @param <K> the type of elements
 */
public interface Stack<K> {
    /**
     * Push element onto the top of the stack
     * @param o the element to push
     */
    void push(K o);
    
    /**
     * Pop element from the top of the stack
     * @return the top element
     * @throws NoSuchElementException if stack is empty
     */
    K pop();
    
    /**
     * Test if the stack is empty
     * @return true if the stack contains no elements
     */
    boolean isEmpty();
    
    /**
     * Peek at the top element without removing it (optional operation)
     * @return the top element
     * @throws NoSuchElementException if stack is empty
     * @throws UnsupportedOperationException if not supported
     */
    K top();
    
    /**
     * Peek at the i-th element from the top (optional operation)
     * @param i distance from top (0 = top element, 1 = second from top, etc.)
     * @return the element at position i from top
     * @throws IndexOutOfBoundsException if i is invalid
     * @throws UnsupportedOperationException if not supported
     */
    K peek(int i);
}

Usage Examples:

import it.unimi.dsi.fastutil.objects.*;

// Create stack implementation
ObjectArrayList<String> stackImpl = new ObjectArrayList<>();
Stack<String> stack = new AbstractStack<String>() {
    public void push(String o) { stackImpl.add(o); }
    public String pop() { return stackImpl.remove(stackImpl.size() - 1); }
    public boolean isEmpty() { return stackImpl.isEmpty(); }
    public String top() { return stackImpl.get(stackImpl.size() - 1); }
    public String peek(int i) { return stackImpl.get(stackImpl.size() - 1 - i); }
};

// Use stack operations
stack.push("first");
stack.push("second"); 
stack.push("third");

// Peek at elements without removing
System.out.println("Top: " + stack.top());        // "third"
System.out.println("Second: " + stack.peek(1));   // "second"
System.out.println("Bottom: " + stack.peek(2));   // "first"

// Pop elements
while (!stack.isEmpty()) {
    System.out.println("Popped: " + stack.pop());
    // Popped: third
    // Popped: second
    // Popped: first
}

Abstract Base Classes

Abstract implementations providing common functionality for priority queues and stacks.

/**
 * Abstract base class for priority queue implementations
 * @param <K> the type of elements
 */
public abstract class AbstractPriorityQueue<K> implements PriorityQueue<K> {
    /**
     * Default implementation throws UnsupportedOperationException
     * @return the last element
     * @throws UnsupportedOperationException always
     */
    public K last() {
        throw new UnsupportedOperationException();
    }
    
    /**
     * Default implementation throws UnsupportedOperationException  
     * @throws UnsupportedOperationException always
     */
    public void changed() {
        throw new UnsupportedOperationException();
    }
    
    /**
     * Default implementation returns null (natural ordering)
     * @return null
     */
    public Comparator<? super K> comparator() {
        return null;
    }
}

/**
 * Abstract base class for indirect priority queue implementations
 */
public abstract class AbstractIndirectPriorityQueue implements IndirectPriorityQueue {
    /**
     * Default implementation throws UnsupportedOperationException
     * @return the last index
     * @throws UnsupportedOperationException always
     */
    public int last() {
        throw new UnsupportedOperationException();
    }
    
    /**
     * Default implementation throws UnsupportedOperationException
     * @throws UnsupportedOperationException always
     */
    public void changed() {
        throw new UnsupportedOperationException();
    }
    
    /**
     * Default implementation throws UnsupportedOperationException
     * @param i the index of changed element
     * @throws UnsupportedOperationException always
     */
    public void changed(int i) {
        throw new UnsupportedOperationException();
    }
    
    /**
     * Default implementation throws UnsupportedOperationException
     * @throws UnsupportedOperationException always
     */
    public void allChanged() {
        throw new UnsupportedOperationException();
    }
}

/**
 * Abstract base class for stack implementations
 * @param <K> the type of elements
 */
public abstract class AbstractStack<K> implements Stack<K> {
    /**
     * Default implementation throws UnsupportedOperationException
     * @return the top element
     * @throws UnsupportedOperationException always
     */
    public K top() {
        throw new UnsupportedOperationException();
    }
    
    /**
     * Default implementation throws UnsupportedOperationException
     * @param i distance from top
     * @return the element at position i
     * @throws UnsupportedOperationException always
     */
    public K peek(int i) {
        throw new UnsupportedOperationException();
    }
}

Utility Classes

Utility classes providing helper methods for creating synchronized wrappers and other operations.

/**
 * Utility class for priority queue operations
 */
public class PriorityQueues {
    /**
     * Create synchronized wrapper for priority queue
     * @param q the priority queue to wrap
     * @return synchronized priority queue
     */
    public static <K> PriorityQueue<K> synchronize(PriorityQueue<K> q);
    
    /**
     * Create synchronized wrapper with custom lock object
     * @param q the priority queue to wrap
     * @param sync the lock object to use
     * @return synchronized priority queue
     */
    public static <K> PriorityQueue<K> synchronize(PriorityQueue<K> q, Object sync);
    
    // Type-specific synchronization methods for primitive priority queues
    public static IntPriorityQueue synchronize(IntPriorityQueue q);
    public static LongPriorityQueue synchronize(LongPriorityQueue q);
    public static DoublePriorityQueue synchronize(DoublePriorityQueue q);
    // ... similar methods for other primitive types
}

/**
 * Utility class for indirect priority queue operations
 */
public class IndirectPriorityQueues {
    /**
     * Create synchronized wrapper for indirect priority queue
     * @param q the indirect priority queue to wrap
     * @return synchronized indirect priority queue
     */
    public static IndirectPriorityQueue synchronize(IndirectPriorityQueue q);
    
    /**
     * Create synchronized wrapper with custom lock object
     * @param q the indirect priority queue to wrap
     * @param sync the lock object to use
     * @return synchronized indirect priority queue
     */
    public static IndirectPriorityQueue synchronize(IndirectPriorityQueue q, Object sync);
}

Usage Examples:

import it.unimi.dsi.fastutil.objects.*;
import it.unimi.dsi.fastutil.ints.*;

// Create thread-safe priority queue
ObjectHeapPriorityQueue<String> originalQueue = new ObjectHeapPriorityQueue<>();
PriorityQueue<String> syncQueue = PriorityQueues.synchronize(originalQueue);

// Use from multiple threads safely
syncQueue.enqueue("thread-safe-item");
String item = syncQueue.dequeue();

// Create thread-safe indirect priority queue
String[] data = {"a", "b", "c"};
ObjectHeapIndirectPriorityQueue<String> originalIndirect = 
    new ObjectHeapIndirectPriorityQueue<>(data);
IndirectPriorityQueue syncIndirect = IndirectPriorityQueues.synchronize(originalIndirect);

// Thread-safe indirect operations
syncIndirect.enqueue(0);
int index = syncIndirect.dequeue();

// Type-specific synchronized priority queue
IntHeapPriorityQueue intQueue = new IntHeapPriorityQueue();
IntPriorityQueue syncIntQueue = PriorityQueues.synchronize(intQueue);
syncIntQueue.enqueue(42);
int value = syncIntQueue.dequeueInt(); // Type-specific dequeue

Implementation Classes

Priority Queue Implementations

ObjectHeapPriorityQueue<K>

  • Heap-based priority queue for objects
  • Efficient O(log n) enqueue/dequeue operations
  • Supports custom comparators

Type-Specific Priority Queues

  • IntHeapPriorityQueue, LongHeapPriorityQueue, etc.
  • Primitive-optimized versions avoiding boxing overhead
  • Methods like enqueueInt(), dequeueInt() for direct primitive access

Indirect Priority Queue Implementations

ObjectHeapIndirectPriorityQueue<K>

  • Heap-based indirect priority queue for objects
  • Maintains separate element storage and index-based priority ordering
  • Supports element change notifications

Type-Specific Indirect Priority Queues

  • IntHeapIndirectPriorityQueue, LongHeapIndirectPriorityQueue, etc.
  • Optimized for primitive element types
  • Direct primitive access methods

Performance Characteristics

  • Priority Queues: O(log n) enqueue/dequeue, O(1) peek operations
  • Indirect Priority Queues: O(log n) operations with additional O(1) contains/remove by index
  • Synchronized Wrappers: Same complexity with synchronization overhead
  • Memory Usage: Heap-based implementations use compact array storage

Usage Guidelines

  1. Choose Direct vs Indirect: Use indirect queues when elements are stored separately or when you need to modify priorities of existing elements
  2. Thread Safety: Use synchronized wrappers for multi-threaded access
  3. Primitive Types: Use type-specific implementations to avoid boxing overhead
  4. Change Notifications: Call changed() methods after modifying elements in-place for indirect queues
  5. Comparators: Provide appropriate comparators for custom ordering requirements

Install with Tessl CLI

npx tessl i tessl/maven-it-unimi-dsi--fastutil

docs

big-data-structures.md

core-utilities.md

index.md

io-streams.md

priority-queues-stacks.md

type-specific-collections.md

tile.json