CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-eclipse-collections--eclipse-collections

A comprehensive collections library for Java delivering productivity and performance through an expressive and efficient set of APIs and types.

Pending
Overview
Eval results
Files

advanced-features.mddocs/

Advanced Features

Eclipse Collections provides advanced collection types and utility APIs for specialized use cases including Multimaps, BiMaps, Partitions, and various container types with sophisticated operations.

Capabilities

Multimap Operations

Multimaps provide one-to-many key-value relationships where each key can map to multiple values.

/**
 * Base multimap interface providing one-to-many key-value relationships
 */
interface Multimap<K, V> {
    // Size and capacity operations
    /**
     * Returns total number of key-value pairs
     * @return total size of multimap
     */
    int size();
    
    /**
     * Returns number of distinct keys
     * @return count of unique keys
     */
    int sizeDistinct();
    
    /**
     * Tests if multimap is empty
     * @return true if no key-value pairs exist
     */
    boolean isEmpty();
    
    /**
     * Tests if multimap is not empty
     * @return true if key-value pairs exist
     */
    boolean notEmpty();
    
    // Key-value operations
    /**
     * Associates key with value
     * @param key key to associate
     * @param value value to associate with key
     * @return true if multimap was modified
     */
    boolean put(K key, V value);
    
    /**
     * Associates key with multiple values
     * @param key key to associate
     * @param values values to associate with key
     * @return true if multimap was modified
     */
    boolean putAll(K key, Iterable<? extends V> values);
    
    /**
     * Associates all key-value pairs from another multimap
     * @param multimap source multimap to copy from
     * @return true if this multimap was modified
     */
    boolean putAll(Multimap<? extends K, ? extends V> multimap);
    
    // Retrieval operations
    /**
     * Gets all values associated with key
     * @param key key to retrieve values for
     * @return RichIterable of values for key (empty if key not found)
     */
    RichIterable<V> get(K key);
    
    /**
     * Tests if key exists in multimap
     * @param key key to test
     * @return true if key has associated values
     */
    boolean containsKey(Object key);
    
    /**
     * Tests if value exists in multimap
     * @param value value to test
     * @return true if value is associated with any key
     */
    boolean containsValue(Object value);
    
    /**
     * Tests if specific key-value pair exists
     * @param key key to test
     * @param value value to test
     * @return true if key-value pair exists
     */
    boolean containsKeyValuePair(Object key, Object value);
    
    // Removal operations
    /**
     * Removes specific key-value pair
     * @param key key to remove from
     * @param value value to remove
     * @return true if pair was removed
     */
    boolean remove(Object key, Object value);
    
    /**
     * Removes all values for key
     * @param key key to remove all values for
     * @return RichIterable of removed values
     */
    RichIterable<V> removeAll(Object key);
    
    /**
     * Removes all key-value pairs
     */
    void clear();
    
    // Views and iteration
    /**
     * Gets view of all distinct keys
     * @return RichIterable of keys
     */
    RichIterable<K> keysView();
    
    /**
     * Gets view of all values (including duplicates)
     * @return RichIterable of all values
     */
    RichIterable<V> valuesView();
    
    /**
     * Gets view of keys with their occurrence counts
     * @return Bag mapping keys to occurrence counts
     */
    Bag<K> keyBag();
    
    /**
     * Gets view of key-multivalues pairs
     * @return RichIterable of Pairs where each pair contains key and its values collection
     */
    RichIterable<Pair<K, RichIterable<V>>> keyMultiValuePairsView();
    
    /**
     * Gets view of individual key-value pairs
     * @return RichIterable of individual Pairs
     */
    RichIterable<Pair<K, V>> keyValuePairsView();
    
    // Transformation operations
    /**
     * Create new multimap with keys and values swapped
     * @return Multimap with flipped key-value relationships
     */
    Multimap<V, K> flip();
    
    /**
     * Filter key-value pairs based on predicate
     * @param predicate predicate to test key-value pairs
     * @return new Multimap with pairs matching predicate
     */
    Multimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
    
    /**
     * Filter out key-value pairs based on predicate
     * @param predicate predicate to test key-value pairs
     * @return new Multimap with pairs not matching predicate
     */
    Multimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
    
    /**
     * Filter keys based on predicate
     * @param predicate predicate to test keys
     * @return new Multimap with keys matching predicate
     */
    Multimap<K, V> selectKeysMultiValues(Predicate2<? super K, ? super RichIterable<V>> predicate);
    
    /**
     * Transform key-value pairs
     * @param function function to transform key-value pairs
     * @return new Multimap with transformed pairs
     */
    <K2, V2> Multimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
    
    /**
     * Transform keys
     * @param function function to transform keys
     * @return new Multimap with transformed keys
     */
    <NK> Multimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
    
    /**
     * Transform values
     * @param function function to transform values
     * @return new Multimap with transformed values
     */
    <NV> Multimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
    
    // Grouping operations
    /**
     * Group values by applying function to each value
     * @param function function to compute grouping key from values
     * @return new Multimap grouped by function results
     */
    <NV> Multimap<NV, V> groupBy(Function<? super V, ? extends NV> function);
    
    // Conversion operations
    /**
     * Convert to regular map with collection values
     * @return MutableMap where values are collections
     */
    MutableMap<K, RichIterable<V>> toMap();
    
    /**
     * Convert to map with lists as values
     * @return MutableMapIterable with List values
     */
    MutableMapIterable<K, RichIterable<V>> toMapWithTarget();
}

/**
 * Mutable multimap interface
 */
interface MutableMultimap<K, V> extends Multimap<K, V> {
    // Fluent API methods
    MutableMultimap<K, V> withKeyValue(K key, V value);
    MutableMultimap<K, V> withKeyMultiValues(K key, V... values);
    MutableMultimap<K, V> withoutKey(K key);
    MutableMultimap<K, V> withoutKeyValue(K key, V value);
    
    // Mutable transformations
    MutableMultimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
    MutableMultimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
    <K2, V2> MutableMultimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
    <NK> MutableMultimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
    <NV> MutableMultimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
    
    // Immutable view
    ImmutableMultimap<K, V> toImmutable();
}

/**
 * Immutable multimap interface
 */
interface ImmutableMultimap<K, V> extends Multimap<K, V> {
    // Immutable modification operations
    ImmutableMultimap<K, V> newWith(K key, V value);
    ImmutableMultimap<K, V> newWithAll(K key, Iterable<? extends V> values);
    ImmutableMultimap<K, V> newWithoutKey(K key);
    ImmutableMultimap<K, V> newWithout(Object key, Object value);
    
    // Immutable transformations  
    ImmutableMultimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
    ImmutableMultimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
    <K2, V2> ImmutableMultimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
    <NK> ImmutableMultimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
    <NV> ImmutableMultimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
}

Specific Multimap Types

Different multimap implementations provide various value collection behaviors.

/**
 * Multimap that stores values as lists (preserves insertion order, allows duplicates)
 */
interface ListMultimap<K, V> extends Multimap<K, V> {
    /**
     * Gets values as a list for the specified key
     * @param key key to get values for
     * @return MutableList of values (empty list if key not found)
     */
    MutableList<V> get(K key);
    
    // Transformation operations return ListMultimaps
    ListMultimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
    ListMultimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
    <K2, V2> ListMultimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
    <NK> ListMultimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
    <NV> ListMultimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
}

/**
 * Multimap that stores values as sets (no duplicates)
 */
interface SetMultimap<K, V> extends Multimap<K, V> {
    /**
     * Gets values as a set for the specified key
     * @param key key to get values for
     * @return MutableSet of values (empty set if key not found)
     */
    MutableSet<V> get(K key);
    
    // Set-specific transformation operations
    SetMultimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
    SetMultimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
    <K2, V2> SetMultimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
    <NK> SetMultimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
    <NV> SetMultimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
}

/**
 * Multimap that stores values as bags (allows duplicates with counts)
 */
interface BagMultimap<K, V> extends Multimap<K, V> {
    /**
     * Gets values as a bag for the specified key
     * @param key key to get values for
     * @return MutableBag of values with occurrence counts (empty bag if key not found)
     */
    MutableBag<V> get(K key);
    
    // Bag-specific transformation operations
    BagMultimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
    BagMultimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
    <K2, V2> BagMultimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
    <NK> BagMultimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
    <NV> BagMultimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
}

/**
 * Multimap that stores values as sorted sets
 */
interface SortedSetMultimap<K, V> extends SetMultimap<K, V> {
    /**
     * Gets values as a sorted set for the specified key
     * @param key key to get values for
     * @return MutableSortedSet of values (empty sorted set if key not found)
     */
    MutableSortedSet<V> get(K key);
    
    /**
     * Gets the comparator used for sorting values
     * @return Comparator used for value ordering
     */
    Comparator<? super V> comparator();
}

/**
 * Multimap that stores values as sorted bags
 */
interface SortedBagMultimap<K, V> extends BagMultimap<K, V> {
    /**
     * Gets values as a sorted bag for the specified key
     * @param key key to get values for
     * @return MutableSortedBag of values (empty sorted bag if key not found)
     */
    MutableSortedBag<V> get(K key);
    
    /**
     * Gets the comparator used for sorting values
     * @return Comparator used for value ordering
     */
    Comparator<? super V> comparator();
}

Usage Examples:

import org.eclipse.collections.impl.factory.Multimaps;

// Create different types of multimaps
MutableListMultimap<String, Integer> listMultimap = Multimaps.mutable.list.empty();
MutableSetMultimap<String, String> setMultimap = Multimaps.mutable.set.empty();
MutableBagMultimap<String, String> bagMultimap = Multimaps.mutable.bag.empty();

// ListMultimap preserves order and allows duplicates
listMultimap.put("numbers", 1);
listMultimap.put("numbers", 2);
listMultimap.put("numbers", 1); // Duplicate allowed
MutableList<Integer> numbers = listMultimap.get("numbers"); // [1, 2, 1]

// SetMultimap prevents duplicates
setMultimap.put("colors", "red");
setMultimap.put("colors", "blue");
setMultimap.put("colors", "red"); // Duplicate ignored
MutableSet<String> colors = setMultimap.get("colors"); // [red, blue]

// BagMultimap tracks occurrence counts  
bagMultimap.put("words", "hello");
bagMultimap.put("words", "world");
bagMultimap.put("words", "hello"); // Tracked as second occurrence
MutableBag<String> words = bagMultimap.get("words"); // {hello=2, world=1}

// Multimap operations
Multimap<String, Integer> flipped = listMultimap.flip(); // Values become keys

// Group a list into multimap
List<Person> people = Arrays.asList(
    new Person("Alice", "Engineering"),
    new Person("Bob", "Sales"),
    new Person("Charlie", "Engineering")
);
ListMultimap<String, Person> peopleByDepartment = people
    .stream()
    .collect(Multimaps.toListMultimap(Person::getDepartment, Function.identity()));

Partition APIs

Partition APIs split collections into two groups based on a predicate.

/**
 * Base partition interface splitting collection into selected and rejected elements
 */
interface PartitionIterable<T> {
    /**
     * Gets elements that satisfied the partitioning predicate
     * @return RichIterable of selected elements
     */
    RichIterable<T> getSelected();
    
    /**
     * Gets elements that did not satisfy the partitioning predicate
     * @return RichIterable of rejected elements
     */
    RichIterable<T> getRejected();
}

/**
 * Mutable partition interface
 */
interface PartitionMutableCollection<T> extends PartitionIterable<T> {
    /**
     * Gets selected elements as mutable collection
     * @return MutableCollection of selected elements
     */
    MutableCollection<T> getSelected();
    
    /**
     * Gets rejected elements as mutable collection
     * @return MutableCollection of rejected elements
     */
    MutableCollection<T> getRejected();
}

/**
 * Immutable partition interface
 */
interface PartitionImmutableCollection<T> extends PartitionIterable<T> {
    /**
     * Gets selected elements as immutable collection
     * @return ImmutableCollection of selected elements
     */
    ImmutableCollection<T> getSelected();
    
    /**
     * Gets rejected elements as immutable collection
     * @return ImmutableCollection of rejected elements
     */
    ImmutableCollection<T> getRejected();
}

// Type-specific partition interfaces
/**
 * Partition for lists
 */
interface PartitionList<T> extends PartitionIterable<T> {
    MutableList<T> getSelected();
    MutableList<T> getRejected();
}

/**
 * Partition for sets
 */
interface PartitionSet<T> extends PartitionIterable<T> {
    MutableSet<T> getSelected();
    MutableSet<T> getRejected();
}

/**
 * Partition for bags
 */
interface PartitionBag<T> extends PartitionIterable<T> {
    MutableBag<T> getSelected();
    MutableBag<T> getRejected();
}

/**
 * Partition for stacks
 */
interface PartitionStack<T> extends PartitionIterable<T> {
    MutableStack<T> getSelected();
    MutableStack<T> getRejected();
}

Usage Examples:

import org.eclipse.collections.impl.factory.Lists;

MutableList<Integer> numbers = Lists.mutable.with(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Partition into even and odd numbers
PartitionList<Integer> evenOddPartition = numbers.partition(x -> x % 2 == 0);
MutableList<Integer> evens = evenOddPartition.getSelected();  // [2, 4, 6, 8, 10]
MutableList<Integer> odds = evenOddPartition.getRejected();   // [1, 3, 5, 7, 9]

// Partition with parameter
PartitionList<Integer> aboveThreshold = numbers.partitionWith(
    (num, threshold) -> num > threshold, 
    5
);
MutableList<Integer> above5 = aboveThreshold.getSelected();   // [6, 7, 8, 9, 10]
MutableList<Integer> below5 = aboveThreshold.getRejected();   // [1, 2, 3, 4, 5]

// Multiple partitioning
List<String> words = Lists.mutable.with("apple", "banana", "cherry", "date", "elderberry");
PartitionList<String> shortLong = words.partition(word -> word.length() <= 5);
MutableList<String> shortWords = shortLong.getSelected();     // [apple, date]
MutableList<String> longWords = shortLong.getRejected();      // [banana, cherry, elderberry]

BiMap APIs

BiMaps provide bidirectional one-to-one mappings between keys and values.

/**
 * Bidirectional map providing one-to-one mapping between keys and values
 * Both keys and values must be unique
 */
interface BiMap<K, V> extends MapIterable<K, V> {
    /**
     * Get the inverse BiMap where values become keys and keys become values
     * @return BiMap with key-value relationships reversed
     */
    BiMap<V, K> inverse();
    
    /**
     * Put key-value pair, enforcing uniqueness of both keys and values
     * If key already exists, its previous value is removed from value->key mapping
     * If value already exists, its previous key is removed from key->value mapping
     * @param key key to put
     * @param value value to put
     * @return previous value associated with key, or null
     * @throws IllegalArgumentException if putting would create duplicate values
     */
    V put(K key, V value);
}

/**
 * Mutable bidirectional map
 */
interface MutableBiMap<K, V> extends BiMap<K, V>, MutableMap<K, V> {
    /**
     * Force put key-value pair, removing any existing mappings that would conflict
     * This method removes existing mappings to ensure uniqueness constraints
     * @param key key to put
     * @param value value to put  
     * @return previous value associated with key, or null
     */
    V forcePut(K key, V value);
    
    /**
     * Get inverse mutable BiMap
     * @return MutableBiMap with relationships reversed
     */
    MutableBiMap<V, K> inverse();
    
    // Fluent API
    MutableBiMap<K, V> withKeyValue(K key, V value);
    MutableBiMap<K, V> withoutKey(K key);
    MutableBiMap<K, V> withoutAllKeys(Iterable<? extends K> keys);
    
    // Transformations
    MutableBiMap<K, V> select(Predicate2<? super K, ? super V> predicate);
    MutableBiMap<K, V> reject(Predicate2<? super K, ? super V> predicate);
    
    // Immutable view
    ImmutableBiMap<K, V> toImmutable();
}

/**
 * Immutable bidirectional map
 */
interface ImmutableBiMap<K, V> extends BiMap<K, V>, ImmutableMapIterable<K, V> {
    /**
     * Get inverse immutable BiMap
     * @return ImmutableBiMap with relationships reversed
     */
    ImmutableBiMap<V, K> inverse();
    
    // Immutable modification operations
    ImmutableBiMap<K, V> newWithKeyValue(K key, V value);
    ImmutableBiMap<K, V> newWithoutKey(K key);
    ImmutableBiMap<K, V> newWithoutAllKeys(Iterable<? extends K> keys);
    
    // Immutable transformations
    ImmutableBiMap<K, V> select(Predicate2<? super K, ? super V> predicate);
    ImmutableBiMap<K, V> reject(Predicate2<? super K, ? super V> predicate);
}

Usage Examples:

import org.eclipse.collections.impl.bimap.mutable.HashBiMap;

// Create bidirectional mapping between IDs and names  
MutableBiMap<Integer, String> idToName = HashBiMap.newMap();
idToName.put(1, "Alice");
idToName.put(2, "Bob");
idToName.put(3, "Charlie");

// Access in both directions
String name = idToName.get(2);                    // "Bob"
Integer id = idToName.inverse().get("Alice");      // 1

// BiMap enforces uniqueness of both keys and values
idToName.put(4, "Alice"); // This removes the existing mapping 1 -> "Alice"
// Now idToName contains: {2="Bob", 3="Charlie", 4="Alice"}

// Force put removes conflicting mappings
idToName.forcePut(5, "Bob"); // Removes 2 -> "Bob" and adds 5 -> "Bob"
// Now idToName contains: {3="Charlie", 4="Alice", 5="Bob"}

// Use inverse BiMap
MutableBiMap<String, Integer> nameToId = idToName.inverse();
Integer charlieId = nameToId.get("Charlie");       // 3
String idForFive = nameToId.inverse().get(5);      // "Bob"

// BiMaps are useful for lookups in both directions
public class UserService {
    private final MutableBiMap<Long, String> userIdToUsername = HashBiMap.newMap();
    
    public void addUser(Long id, String username) {
        userIdToUsername.put(id, username);
    }
    
    public String getUsernameById(Long id) {
        return userIdToUsername.get(id);
    }
    
    public Long getUserIdByUsername(String username) {
        return userIdToUsername.inverse().get(username);
    }
}

Iterator Types

Enhanced iterator interfaces providing additional functionality.

/**
 * Enhanced iterator with additional methods beyond standard Iterator
 */
interface RichIterator<T> extends Iterator<T> {
    /**
     * Collect remaining elements using transformation function
     * @param function transformation function
     * @return MutableList of transformed elements
     */
    <V> MutableList<V> collect(Function<? super T, ? extends V> function);
    
    /**
     * Select remaining elements matching predicate
     * @param predicate predicate for selection
     * @return MutableList of matching elements
     */
    MutableList<T> select(Predicate<? super T> predicate);
    
    /**
     * Reject remaining elements matching predicate  
     * @param predicate predicate for rejection
     * @return MutableList of non-matching elements
     */
    MutableList<T> reject(Predicate<? super T> predicate);
    
    /**
     * Detect first remaining element matching predicate
     * @param predicate predicate for detection
     * @return first matching element or null
     */
    T detect(Predicate<? super T> predicate);
    
    /**
     * Test if any remaining element matches predicate
     * @param predicate predicate to test
     * @return true if any element matches
     */
    boolean anySatisfy(Predicate<? super T> predicate);
    
    /**
     * Test if all remaining elements match predicate
     * @param predicate predicate to test
     * @return true if all elements match
     */
    boolean allSatisfy(Predicate<? super T> predicate);
    
    /**
     * Count remaining elements matching predicate
     * @param predicate predicate for counting
     * @return count of matching elements
     */
    int count(Predicate<? super T> predicate);
    
    /**
     * Collect remaining elements to list
     * @return MutableList of remaining elements
     */
    MutableList<T> toList();
}

/**
 * Mutable iterator supporting removal operations
 */
interface MutableIterator<T> extends Iterator<T> {
    /**
     * Remove current element (standard Iterator method)
     */
    void remove();
}

// Primitive iterators for each primitive type
/**
 * Iterator for int primitives
 */
interface IntIterator {
    /**
     * Test if more int elements available
     * @return true if more elements exist
     */
    boolean hasNext();
    
    /**
     * Get next int element
     * @return next int value
     * @throws NoSuchElementException if no more elements
     */
    int next();
}

// Similar primitive iterators exist for:
// BooleanIterator, ByteIterator, CharIterator, ShortIterator
// LongIterator, FloatIterator, DoubleIterator

Ordered Collections

Collections with defined iteration order providing positional operations.

/**
 * Base interface for collections with defined iteration order
 */
interface OrderedIterable<T> extends RichIterable<T> {
    /**
     * Get first element
     * @return first element
     * @throws NoSuchElementException if empty
     */
    T getFirst();
    
    /**
     * Get last element
     * @return last element
     * @throws NoSuchElementException if empty
     */
    T getLast();
    
    /**
     * Find index of object in ordered collection
     * @param object object to find
     * @return index of object or -1 if not found
     */
    int indexOf(Object object);
    
    /**
     * Get element at index
     * @param index index to retrieve
     * @return element at index
     * @throws IndexOutOfBoundsException if index invalid
     */
    T get(int index);
    
    // Positional operations
    /**
     * Take first N elements
     * @param count number of elements to take
     * @return OrderedIterable of first N elements
     */
    OrderedIterable<T> take(int count);
    
    /**
     * Drop first N elements
     * @param count number of elements to drop
     * @return OrderedIterable without first N elements
     */
    OrderedIterable<T> drop(int count);
    
    /**
     * Take elements while predicate is true
     * @param predicate condition to test elements
     * @return OrderedIterable of elements taken while condition holds
     */
    OrderedIterable<T> takeWhile(Predicate<? super T> predicate);
    
    /**
     * Drop elements while predicate is true
     * @param predicate condition to test elements
     * @return OrderedIterable after dropping elements while condition holds
     */
    OrderedIterable<T> dropWhile(Predicate<? super T> predicate);
    
    /**
     * Remove consecutive duplicate elements preserving order
     * @return OrderedIterable with duplicates removed
     */
    OrderedIterable<T> distinct();
    
    /**
     * Reverse the order of elements
     * @return OrderedIterable with reversed order
     */
    OrderedIterable<T> toReversed();
    
    // Zipping operations
    /**
     * Zip with another iterable creating pairs
     * @param that iterable to zip with
     * @return OrderedIterable of Pairs
     */
    <S> OrderedIterable<Pair<T, S>> zip(Iterable<S> that);
    
    /**
     * Zip with indices creating index-element pairs
     * @return OrderedIterable of Pairs containing elements and their indices
     */
    OrderedIterable<Pair<T, Integer>> zipWithIndex();
}

/**
 * Mutable ordered collection
 */
interface MutableOrderedIterable<T> extends OrderedIterable<T>, MutableCollection<T> {
    // Mutable positional operations
    MutableOrderedIterable<T> take(int count);
    MutableOrderedIterable<T> drop(int count);
    MutableOrderedIterable<T> takeWhile(Predicate<? super T> predicate);
    MutableOrderedIterable<T> dropWhile(Predicate<? super T> predicate);
    MutableOrderedIterable<T> distinct();
    MutableOrderedIterable<T> toReversed();
    
    // Mutable zipping
    <S> MutableOrderedIterable<Pair<T, S>> zip(Iterable<S> that);
    MutableOrderedIterable<Pair<T, Integer>> zipWithIndex();
}

Usage Examples:

import org.eclipse.collections.impl.factory.Lists;

MutableList<Integer> numbers = Lists.mutable.with(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Positional operations
OrderedIterable<Integer> firstFive = numbers.take(5);         // [1, 2, 3, 4, 5]
OrderedIterable<Integer> lastFive = numbers.drop(5);          // [6, 7, 8, 9, 10]
OrderedIterable<Integer> whileLessThan5 = numbers.takeWhile(x -> x < 5); // [1, 2, 3, 4]
OrderedIterable<Integer> afterGreaterThan5 = numbers.dropWhile(x -> x <= 5); // [6, 7, 8, 9, 10]

// Zipping operations
List<String> letters = Lists.mutable.with("A", "B", "C", "D", "E");
OrderedIterable<Pair<Integer, String>> zipped = numbers.take(5).zip(letters);
// [(1,A), (2,B), (3,C), (4,D), (5,E)]

OrderedIterable<Pair<Integer, Integer>> withIndex = numbers.take(3).zipWithIndex();
// [(1,0), (2,1), (3,2)]

// Distinct operation
List<Integer> withDuplicates = Lists.mutable.with(1, 2, 2, 3, 3, 3, 4, 4, 5);
OrderedIterable<Integer> uniqueValues = withDuplicates.distinct(); // [1, 2, 3, 4, 5]

Utility Collections and Features

Additional specialized collection types and features.

/**
 * Collection that maintains fixed size after creation
 * Modification operations that would change size throw UnsupportedOperationException
 */
interface FixedSizeCollection<T> extends MutableCollection<T> {
    // Available operations: set, replace, sort, reverse
    // Not available: add, remove, clear (size-changing operations)
}

/**
 * Thread-safe collection optimized for multiple readers with single writer
 */
interface MultiReaderCollection<T> extends MutableCollection<T> {
    /**
     * Acquire read lock for thread-safe read operations
     * @return read lock
     */
    Lock getReadLock();
    
    /**
     * Acquire write lock for thread-safe write operations
     * @return write lock
     */  
    Lock getWriteLock();
    
    /**
     * Execute read operation with automatic read lock management
     * @param procedure read operation to perform
     */
    void withReadLockAndDelegate(Procedure<? super MutableCollection<T>> procedure);
    
    /**
     * Execute write operation with automatic write lock management
     * @param procedure write operation to perform
     */
    void withWriteLockAndDelegate(Procedure<? super MutableCollection<T>> procedure);
}

/**
 * Collection using custom hashing strategy instead of object's hashCode/equals
 */
interface MutableCollectionWithHashingStrategy<T> extends MutableCollection<T> {
    /**
     * Get the hashing strategy used by this collection
     * @return HashingStrategy instance
     */
    HashingStrategy<? super T> hashingStrategy();
}

/**
 * Custom hashing and equality strategy interface
 */
interface HashingStrategy<T> {
    /**
     * Compute hash code for object using custom strategy
     * @param object object to compute hash for
     * @return hash code
     */
    int computeHashCode(T object);
    
    /**
     * Test equality using custom strategy
     * @param object1 first object
     * @param object2 second object
     * @return true if objects are equal according to strategy
     */
    boolean equals(T object1, T object2);
}

Usage Examples:

import org.eclipse.collections.impl.collection.mutable.CollectionAdapter;
import org.eclipse.collections.impl.set.strategy.mutable.MutableHashingStrategySet;

// Fixed-size collections
FixedSizeList<String> fixedList = Lists.fixedSize.with("A", "B", "C");
// fixedList.add("D"); // Throws UnsupportedOperationException
fixedList.set(0, "X"); // OK - doesn't change size

// Custom hashing strategy for case-insensitive strings  
HashingStrategy<String> caseInsensitive = new HashingStrategy<String>() {
    public int computeHashCode(String string) {
        return string == null ? 0 : string.toLowerCase().hashCode();
    }
    
    public boolean equals(String s1, String s2) {
        return s1 == null ? s2 == null : s1.equalsIgnoreCase(s2);
    }
};

MutableSet<String> caseInsensitiveSet = new MutableHashingStrategySet<>(caseInsensitive);
caseInsensitiveSet.add("Hello");
caseInsensitiveSet.add("HELLO");  // Not added - considered duplicate
caseInsensitiveSet.add("World");
// Set contains: ["Hello", "World"] (case-insensitive duplicates removed)

// Multi-reader collections for concurrent access
MultiReaderList<String> concurrentList = MultiReaderFastList.newList();
concurrentList.add("item1");
concurrentList.add("item2");

// Thread-safe read operation
concurrentList.withReadLockAndDelegate(list -> {
    // Perform read operations
    int size = list.size();
    boolean contains = list.contains("item1");
});

// Thread-safe write operation  
concurrentList.withWriteLockAndDelegate(list -> {
    // Perform write operations
    list.add("item3");
    list.remove("item1");
});

Integration Patterns

Converting Between Collection Types

Eclipse Collections provides seamless conversion between different collection types:

// Convert between mutable and immutable
MutableList<String> mutableList = Lists.mutable.with("A", "B", "C");
ImmutableList<String> immutableList = mutableList.toImmutable();
MutableList<String> backToMutable = immutableList.toList();

// Convert between different collection types
MutableSet<String> set = mutableList.toSet();
MutableBag<String> bag = mutableList.toBag();
MutableStack<String> stack = Stacks.mutable.withAll(mutableList);

// Convert to JDK collections
List<String> jdkList = mutableList.castToList();
Set<String> jdkSet = set.castToSet();
Map<String, String> jdkMap = Maps.mutable.with("key1", "value1").castToMap();

// Convert from JDK collections
List<String> jdkSource = Arrays.asList("X", "Y", "Z");
MutableList<String> adapted = ListAdapter.adapt(jdkSource);
MutableList<String> copied = Lists.mutable.withAll(jdkSource);

Performance Optimization Patterns

Use Eclipse Collections features for optimal performance:

// Use primitive collections to avoid boxing
MutableIntList primitiveInts = IntLists.mutable.with(1, 2, 3, 4, 5);
long sum = primitiveInts.sum(); // No boxing

// Use lazy evaluation for large datasets
LazyIterable<String> lazy = hugeMutableList
    .asLazy()
    .select(expensive::predicate)
    .collect(expensive::transformation)
    .select(another::predicate);
// Only computed when terminal operation called
MutableList<String> result = lazy.toList();

// Use parallel processing for CPU-intensive operations
MutableList<ComplexObject> processed = hugeList
    .asParallel(ForkJoinPool.commonPool(), 1000)
    .collect(ComplexObject::expensiveTransformation)
    .toList();

// Use immutable collections for thread safety without locks
ImmutableList<String> threadSafeList = Lists.immutable.with("A", "B", "C");
// Can be safely shared across threads without synchronization

Install with Tessl CLI

npx tessl i tessl/maven-org-eclipse-collections--eclipse-collections

docs

advanced-features.md

core-interfaces.md

factory-methods.md

functional-programming.md

index.md

primitive-collections.md

tile.json