0
# Advanced Features
1
2
Eclipse Collections provides advanced collection types and utility APIs for specialized use cases including Multimaps, BiMaps, Partitions, and various container types with sophisticated operations.
3
4
## Capabilities
5
6
### Multimap Operations
7
8
Multimaps provide one-to-many key-value relationships where each key can map to multiple values.
9
10
```java { .api }
11
/**
12
* Base multimap interface providing one-to-many key-value relationships
13
*/
14
interface Multimap<K, V> {
15
// Size and capacity operations
16
/**
17
* Returns total number of key-value pairs
18
* @return total size of multimap
19
*/
20
int size();
21
22
/**
23
* Returns number of distinct keys
24
* @return count of unique keys
25
*/
26
int sizeDistinct();
27
28
/**
29
* Tests if multimap is empty
30
* @return true if no key-value pairs exist
31
*/
32
boolean isEmpty();
33
34
/**
35
* Tests if multimap is not empty
36
* @return true if key-value pairs exist
37
*/
38
boolean notEmpty();
39
40
// Key-value operations
41
/**
42
* Associates key with value
43
* @param key key to associate
44
* @param value value to associate with key
45
* @return true if multimap was modified
46
*/
47
boolean put(K key, V value);
48
49
/**
50
* Associates key with multiple values
51
* @param key key to associate
52
* @param values values to associate with key
53
* @return true if multimap was modified
54
*/
55
boolean putAll(K key, Iterable<? extends V> values);
56
57
/**
58
* Associates all key-value pairs from another multimap
59
* @param multimap source multimap to copy from
60
* @return true if this multimap was modified
61
*/
62
boolean putAll(Multimap<? extends K, ? extends V> multimap);
63
64
// Retrieval operations
65
/**
66
* Gets all values associated with key
67
* @param key key to retrieve values for
68
* @return RichIterable of values for key (empty if key not found)
69
*/
70
RichIterable<V> get(K key);
71
72
/**
73
* Tests if key exists in multimap
74
* @param key key to test
75
* @return true if key has associated values
76
*/
77
boolean containsKey(Object key);
78
79
/**
80
* Tests if value exists in multimap
81
* @param value value to test
82
* @return true if value is associated with any key
83
*/
84
boolean containsValue(Object value);
85
86
/**
87
* Tests if specific key-value pair exists
88
* @param key key to test
89
* @param value value to test
90
* @return true if key-value pair exists
91
*/
92
boolean containsKeyValuePair(Object key, Object value);
93
94
// Removal operations
95
/**
96
* Removes specific key-value pair
97
* @param key key to remove from
98
* @param value value to remove
99
* @return true if pair was removed
100
*/
101
boolean remove(Object key, Object value);
102
103
/**
104
* Removes all values for key
105
* @param key key to remove all values for
106
* @return RichIterable of removed values
107
*/
108
RichIterable<V> removeAll(Object key);
109
110
/**
111
* Removes all key-value pairs
112
*/
113
void clear();
114
115
// Views and iteration
116
/**
117
* Gets view of all distinct keys
118
* @return RichIterable of keys
119
*/
120
RichIterable<K> keysView();
121
122
/**
123
* Gets view of all values (including duplicates)
124
* @return RichIterable of all values
125
*/
126
RichIterable<V> valuesView();
127
128
/**
129
* Gets view of keys with their occurrence counts
130
* @return Bag mapping keys to occurrence counts
131
*/
132
Bag<K> keyBag();
133
134
/**
135
* Gets view of key-multivalues pairs
136
* @return RichIterable of Pairs where each pair contains key and its values collection
137
*/
138
RichIterable<Pair<K, RichIterable<V>>> keyMultiValuePairsView();
139
140
/**
141
* Gets view of individual key-value pairs
142
* @return RichIterable of individual Pairs
143
*/
144
RichIterable<Pair<K, V>> keyValuePairsView();
145
146
// Transformation operations
147
/**
148
* Create new multimap with keys and values swapped
149
* @return Multimap with flipped key-value relationships
150
*/
151
Multimap<V, K> flip();
152
153
/**
154
* Filter key-value pairs based on predicate
155
* @param predicate predicate to test key-value pairs
156
* @return new Multimap with pairs matching predicate
157
*/
158
Multimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
159
160
/**
161
* Filter out key-value pairs based on predicate
162
* @param predicate predicate to test key-value pairs
163
* @return new Multimap with pairs not matching predicate
164
*/
165
Multimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
166
167
/**
168
* Filter keys based on predicate
169
* @param predicate predicate to test keys
170
* @return new Multimap with keys matching predicate
171
*/
172
Multimap<K, V> selectKeysMultiValues(Predicate2<? super K, ? super RichIterable<V>> predicate);
173
174
/**
175
* Transform key-value pairs
176
* @param function function to transform key-value pairs
177
* @return new Multimap with transformed pairs
178
*/
179
<K2, V2> Multimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
180
181
/**
182
* Transform keys
183
* @param function function to transform keys
184
* @return new Multimap with transformed keys
185
*/
186
<NK> Multimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
187
188
/**
189
* Transform values
190
* @param function function to transform values
191
* @return new Multimap with transformed values
192
*/
193
<NV> Multimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
194
195
// Grouping operations
196
/**
197
* Group values by applying function to each value
198
* @param function function to compute grouping key from values
199
* @return new Multimap grouped by function results
200
*/
201
<NV> Multimap<NV, V> groupBy(Function<? super V, ? extends NV> function);
202
203
// Conversion operations
204
/**
205
* Convert to regular map with collection values
206
* @return MutableMap where values are collections
207
*/
208
MutableMap<K, RichIterable<V>> toMap();
209
210
/**
211
* Convert to map with lists as values
212
* @return MutableMapIterable with List values
213
*/
214
MutableMapIterable<K, RichIterable<V>> toMapWithTarget();
215
}
216
217
/**
218
* Mutable multimap interface
219
*/
220
interface MutableMultimap<K, V> extends Multimap<K, V> {
221
// Fluent API methods
222
MutableMultimap<K, V> withKeyValue(K key, V value);
223
MutableMultimap<K, V> withKeyMultiValues(K key, V... values);
224
MutableMultimap<K, V> withoutKey(K key);
225
MutableMultimap<K, V> withoutKeyValue(K key, V value);
226
227
// Mutable transformations
228
MutableMultimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
229
MutableMultimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
230
<K2, V2> MutableMultimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
231
<NK> MutableMultimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
232
<NV> MutableMultimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
233
234
// Immutable view
235
ImmutableMultimap<K, V> toImmutable();
236
}
237
238
/**
239
* Immutable multimap interface
240
*/
241
interface ImmutableMultimap<K, V> extends Multimap<K, V> {
242
// Immutable modification operations
243
ImmutableMultimap<K, V> newWith(K key, V value);
244
ImmutableMultimap<K, V> newWithAll(K key, Iterable<? extends V> values);
245
ImmutableMultimap<K, V> newWithoutKey(K key);
246
ImmutableMultimap<K, V> newWithout(Object key, Object value);
247
248
// Immutable transformations
249
ImmutableMultimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
250
ImmutableMultimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
251
<K2, V2> ImmutableMultimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
252
<NK> ImmutableMultimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
253
<NV> ImmutableMultimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
254
}
255
```
256
257
### Specific Multimap Types
258
259
Different multimap implementations provide various value collection behaviors.
260
261
```java { .api }
262
/**
263
* Multimap that stores values as lists (preserves insertion order, allows duplicates)
264
*/
265
interface ListMultimap<K, V> extends Multimap<K, V> {
266
/**
267
* Gets values as a list for the specified key
268
* @param key key to get values for
269
* @return MutableList of values (empty list if key not found)
270
*/
271
MutableList<V> get(K key);
272
273
// Transformation operations return ListMultimaps
274
ListMultimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
275
ListMultimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
276
<K2, V2> ListMultimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
277
<NK> ListMultimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
278
<NV> ListMultimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
279
}
280
281
/**
282
* Multimap that stores values as sets (no duplicates)
283
*/
284
interface SetMultimap<K, V> extends Multimap<K, V> {
285
/**
286
* Gets values as a set for the specified key
287
* @param key key to get values for
288
* @return MutableSet of values (empty set if key not found)
289
*/
290
MutableSet<V> get(K key);
291
292
// Set-specific transformation operations
293
SetMultimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
294
SetMultimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
295
<K2, V2> SetMultimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
296
<NK> SetMultimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
297
<NV> SetMultimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
298
}
299
300
/**
301
* Multimap that stores values as bags (allows duplicates with counts)
302
*/
303
interface BagMultimap<K, V> extends Multimap<K, V> {
304
/**
305
* Gets values as a bag for the specified key
306
* @param key key to get values for
307
* @return MutableBag of values with occurrence counts (empty bag if key not found)
308
*/
309
MutableBag<V> get(K key);
310
311
// Bag-specific transformation operations
312
BagMultimap<K, V> selectKeysValues(Predicate2<? super K, ? super V> predicate);
313
BagMultimap<K, V> rejectKeysValues(Predicate2<? super K, ? super V> predicate);
314
<K2, V2> BagMultimap<K2, V2> collectKeysValues(Function2<? super K, ? super V, Pair<K2, V2>> function);
315
<NK> BagMultimap<NK, V> collectKeys(Function<? super K, ? extends NK> function);
316
<NV> BagMultimap<K, NV> collectValues(Function<? super V, ? extends NV> function);
317
}
318
319
/**
320
* Multimap that stores values as sorted sets
321
*/
322
interface SortedSetMultimap<K, V> extends SetMultimap<K, V> {
323
/**
324
* Gets values as a sorted set for the specified key
325
* @param key key to get values for
326
* @return MutableSortedSet of values (empty sorted set if key not found)
327
*/
328
MutableSortedSet<V> get(K key);
329
330
/**
331
* Gets the comparator used for sorting values
332
* @return Comparator used for value ordering
333
*/
334
Comparator<? super V> comparator();
335
}
336
337
/**
338
* Multimap that stores values as sorted bags
339
*/
340
interface SortedBagMultimap<K, V> extends BagMultimap<K, V> {
341
/**
342
* Gets values as a sorted bag for the specified key
343
* @param key key to get values for
344
* @return MutableSortedBag of values (empty sorted bag if key not found)
345
*/
346
MutableSortedBag<V> get(K key);
347
348
/**
349
* Gets the comparator used for sorting values
350
* @return Comparator used for value ordering
351
*/
352
Comparator<? super V> comparator();
353
}
354
```
355
356
**Usage Examples:**
357
358
```java
359
import org.eclipse.collections.impl.factory.Multimaps;
360
361
// Create different types of multimaps
362
MutableListMultimap<String, Integer> listMultimap = Multimaps.mutable.list.empty();
363
MutableSetMultimap<String, String> setMultimap = Multimaps.mutable.set.empty();
364
MutableBagMultimap<String, String> bagMultimap = Multimaps.mutable.bag.empty();
365
366
// ListMultimap preserves order and allows duplicates
367
listMultimap.put("numbers", 1);
368
listMultimap.put("numbers", 2);
369
listMultimap.put("numbers", 1); // Duplicate allowed
370
MutableList<Integer> numbers = listMultimap.get("numbers"); // [1, 2, 1]
371
372
// SetMultimap prevents duplicates
373
setMultimap.put("colors", "red");
374
setMultimap.put("colors", "blue");
375
setMultimap.put("colors", "red"); // Duplicate ignored
376
MutableSet<String> colors = setMultimap.get("colors"); // [red, blue]
377
378
// BagMultimap tracks occurrence counts
379
bagMultimap.put("words", "hello");
380
bagMultimap.put("words", "world");
381
bagMultimap.put("words", "hello"); // Tracked as second occurrence
382
MutableBag<String> words = bagMultimap.get("words"); // {hello=2, world=1}
383
384
// Multimap operations
385
Multimap<String, Integer> flipped = listMultimap.flip(); // Values become keys
386
387
// Group a list into multimap
388
List<Person> people = Arrays.asList(
389
new Person("Alice", "Engineering"),
390
new Person("Bob", "Sales"),
391
new Person("Charlie", "Engineering")
392
);
393
ListMultimap<String, Person> peopleByDepartment = people
394
.stream()
395
.collect(Multimaps.toListMultimap(Person::getDepartment, Function.identity()));
396
```
397
398
### Partition APIs
399
400
Partition APIs split collections into two groups based on a predicate.
401
402
```java { .api }
403
/**
404
* Base partition interface splitting collection into selected and rejected elements
405
*/
406
interface PartitionIterable<T> {
407
/**
408
* Gets elements that satisfied the partitioning predicate
409
* @return RichIterable of selected elements
410
*/
411
RichIterable<T> getSelected();
412
413
/**
414
* Gets elements that did not satisfy the partitioning predicate
415
* @return RichIterable of rejected elements
416
*/
417
RichIterable<T> getRejected();
418
}
419
420
/**
421
* Mutable partition interface
422
*/
423
interface PartitionMutableCollection<T> extends PartitionIterable<T> {
424
/**
425
* Gets selected elements as mutable collection
426
* @return MutableCollection of selected elements
427
*/
428
MutableCollection<T> getSelected();
429
430
/**
431
* Gets rejected elements as mutable collection
432
* @return MutableCollection of rejected elements
433
*/
434
MutableCollection<T> getRejected();
435
}
436
437
/**
438
* Immutable partition interface
439
*/
440
interface PartitionImmutableCollection<T> extends PartitionIterable<T> {
441
/**
442
* Gets selected elements as immutable collection
443
* @return ImmutableCollection of selected elements
444
*/
445
ImmutableCollection<T> getSelected();
446
447
/**
448
* Gets rejected elements as immutable collection
449
* @return ImmutableCollection of rejected elements
450
*/
451
ImmutableCollection<T> getRejected();
452
}
453
454
// Type-specific partition interfaces
455
/**
456
* Partition for lists
457
*/
458
interface PartitionList<T> extends PartitionIterable<T> {
459
MutableList<T> getSelected();
460
MutableList<T> getRejected();
461
}
462
463
/**
464
* Partition for sets
465
*/
466
interface PartitionSet<T> extends PartitionIterable<T> {
467
MutableSet<T> getSelected();
468
MutableSet<T> getRejected();
469
}
470
471
/**
472
* Partition for bags
473
*/
474
interface PartitionBag<T> extends PartitionIterable<T> {
475
MutableBag<T> getSelected();
476
MutableBag<T> getRejected();
477
}
478
479
/**
480
* Partition for stacks
481
*/
482
interface PartitionStack<T> extends PartitionIterable<T> {
483
MutableStack<T> getSelected();
484
MutableStack<T> getRejected();
485
}
486
```
487
488
**Usage Examples:**
489
490
```java
491
import org.eclipse.collections.impl.factory.Lists;
492
493
MutableList<Integer> numbers = Lists.mutable.with(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
494
495
// Partition into even and odd numbers
496
PartitionList<Integer> evenOddPartition = numbers.partition(x -> x % 2 == 0);
497
MutableList<Integer> evens = evenOddPartition.getSelected(); // [2, 4, 6, 8, 10]
498
MutableList<Integer> odds = evenOddPartition.getRejected(); // [1, 3, 5, 7, 9]
499
500
// Partition with parameter
501
PartitionList<Integer> aboveThreshold = numbers.partitionWith(
502
(num, threshold) -> num > threshold,
503
5
504
);
505
MutableList<Integer> above5 = aboveThreshold.getSelected(); // [6, 7, 8, 9, 10]
506
MutableList<Integer> below5 = aboveThreshold.getRejected(); // [1, 2, 3, 4, 5]
507
508
// Multiple partitioning
509
List<String> words = Lists.mutable.with("apple", "banana", "cherry", "date", "elderberry");
510
PartitionList<String> shortLong = words.partition(word -> word.length() <= 5);
511
MutableList<String> shortWords = shortLong.getSelected(); // [apple, date]
512
MutableList<String> longWords = shortLong.getRejected(); // [banana, cherry, elderberry]
513
```
514
515
### BiMap APIs
516
517
BiMaps provide bidirectional one-to-one mappings between keys and values.
518
519
```java { .api }
520
/**
521
* Bidirectional map providing one-to-one mapping between keys and values
522
* Both keys and values must be unique
523
*/
524
interface BiMap<K, V> extends MapIterable<K, V> {
525
/**
526
* Get the inverse BiMap where values become keys and keys become values
527
* @return BiMap with key-value relationships reversed
528
*/
529
BiMap<V, K> inverse();
530
531
/**
532
* Put key-value pair, enforcing uniqueness of both keys and values
533
* If key already exists, its previous value is removed from value->key mapping
534
* If value already exists, its previous key is removed from key->value mapping
535
* @param key key to put
536
* @param value value to put
537
* @return previous value associated with key, or null
538
* @throws IllegalArgumentException if putting would create duplicate values
539
*/
540
V put(K key, V value);
541
}
542
543
/**
544
* Mutable bidirectional map
545
*/
546
interface MutableBiMap<K, V> extends BiMap<K, V>, MutableMap<K, V> {
547
/**
548
* Force put key-value pair, removing any existing mappings that would conflict
549
* This method removes existing mappings to ensure uniqueness constraints
550
* @param key key to put
551
* @param value value to put
552
* @return previous value associated with key, or null
553
*/
554
V forcePut(K key, V value);
555
556
/**
557
* Get inverse mutable BiMap
558
* @return MutableBiMap with relationships reversed
559
*/
560
MutableBiMap<V, K> inverse();
561
562
// Fluent API
563
MutableBiMap<K, V> withKeyValue(K key, V value);
564
MutableBiMap<K, V> withoutKey(K key);
565
MutableBiMap<K, V> withoutAllKeys(Iterable<? extends K> keys);
566
567
// Transformations
568
MutableBiMap<K, V> select(Predicate2<? super K, ? super V> predicate);
569
MutableBiMap<K, V> reject(Predicate2<? super K, ? super V> predicate);
570
571
// Immutable view
572
ImmutableBiMap<K, V> toImmutable();
573
}
574
575
/**
576
* Immutable bidirectional map
577
*/
578
interface ImmutableBiMap<K, V> extends BiMap<K, V>, ImmutableMapIterable<K, V> {
579
/**
580
* Get inverse immutable BiMap
581
* @return ImmutableBiMap with relationships reversed
582
*/
583
ImmutableBiMap<V, K> inverse();
584
585
// Immutable modification operations
586
ImmutableBiMap<K, V> newWithKeyValue(K key, V value);
587
ImmutableBiMap<K, V> newWithoutKey(K key);
588
ImmutableBiMap<K, V> newWithoutAllKeys(Iterable<? extends K> keys);
589
590
// Immutable transformations
591
ImmutableBiMap<K, V> select(Predicate2<? super K, ? super V> predicate);
592
ImmutableBiMap<K, V> reject(Predicate2<? super K, ? super V> predicate);
593
}
594
```
595
596
**Usage Examples:**
597
598
```java
599
import org.eclipse.collections.impl.bimap.mutable.HashBiMap;
600
601
// Create bidirectional mapping between IDs and names
602
MutableBiMap<Integer, String> idToName = HashBiMap.newMap();
603
idToName.put(1, "Alice");
604
idToName.put(2, "Bob");
605
idToName.put(3, "Charlie");
606
607
// Access in both directions
608
String name = idToName.get(2); // "Bob"
609
Integer id = idToName.inverse().get("Alice"); // 1
610
611
// BiMap enforces uniqueness of both keys and values
612
idToName.put(4, "Alice"); // This removes the existing mapping 1 -> "Alice"
613
// Now idToName contains: {2="Bob", 3="Charlie", 4="Alice"}
614
615
// Force put removes conflicting mappings
616
idToName.forcePut(5, "Bob"); // Removes 2 -> "Bob" and adds 5 -> "Bob"
617
// Now idToName contains: {3="Charlie", 4="Alice", 5="Bob"}
618
619
// Use inverse BiMap
620
MutableBiMap<String, Integer> nameToId = idToName.inverse();
621
Integer charlieId = nameToId.get("Charlie"); // 3
622
String idForFive = nameToId.inverse().get(5); // "Bob"
623
624
// BiMaps are useful for lookups in both directions
625
public class UserService {
626
private final MutableBiMap<Long, String> userIdToUsername = HashBiMap.newMap();
627
628
public void addUser(Long id, String username) {
629
userIdToUsername.put(id, username);
630
}
631
632
public String getUsernameById(Long id) {
633
return userIdToUsername.get(id);
634
}
635
636
public Long getUserIdByUsername(String username) {
637
return userIdToUsername.inverse().get(username);
638
}
639
}
640
```
641
642
### Iterator Types
643
644
Enhanced iterator interfaces providing additional functionality.
645
646
```java { .api }
647
/**
648
* Enhanced iterator with additional methods beyond standard Iterator
649
*/
650
interface RichIterator<T> extends Iterator<T> {
651
/**
652
* Collect remaining elements using transformation function
653
* @param function transformation function
654
* @return MutableList of transformed elements
655
*/
656
<V> MutableList<V> collect(Function<? super T, ? extends V> function);
657
658
/**
659
* Select remaining elements matching predicate
660
* @param predicate predicate for selection
661
* @return MutableList of matching elements
662
*/
663
MutableList<T> select(Predicate<? super T> predicate);
664
665
/**
666
* Reject remaining elements matching predicate
667
* @param predicate predicate for rejection
668
* @return MutableList of non-matching elements
669
*/
670
MutableList<T> reject(Predicate<? super T> predicate);
671
672
/**
673
* Detect first remaining element matching predicate
674
* @param predicate predicate for detection
675
* @return first matching element or null
676
*/
677
T detect(Predicate<? super T> predicate);
678
679
/**
680
* Test if any remaining element matches predicate
681
* @param predicate predicate to test
682
* @return true if any element matches
683
*/
684
boolean anySatisfy(Predicate<? super T> predicate);
685
686
/**
687
* Test if all remaining elements match predicate
688
* @param predicate predicate to test
689
* @return true if all elements match
690
*/
691
boolean allSatisfy(Predicate<? super T> predicate);
692
693
/**
694
* Count remaining elements matching predicate
695
* @param predicate predicate for counting
696
* @return count of matching elements
697
*/
698
int count(Predicate<? super T> predicate);
699
700
/**
701
* Collect remaining elements to list
702
* @return MutableList of remaining elements
703
*/
704
MutableList<T> toList();
705
}
706
707
/**
708
* Mutable iterator supporting removal operations
709
*/
710
interface MutableIterator<T> extends Iterator<T> {
711
/**
712
* Remove current element (standard Iterator method)
713
*/
714
void remove();
715
}
716
717
// Primitive iterators for each primitive type
718
/**
719
* Iterator for int primitives
720
*/
721
interface IntIterator {
722
/**
723
* Test if more int elements available
724
* @return true if more elements exist
725
*/
726
boolean hasNext();
727
728
/**
729
* Get next int element
730
* @return next int value
731
* @throws NoSuchElementException if no more elements
732
*/
733
int next();
734
}
735
736
// Similar primitive iterators exist for:
737
// BooleanIterator, ByteIterator, CharIterator, ShortIterator
738
// LongIterator, FloatIterator, DoubleIterator
739
```
740
741
### Ordered Collections
742
743
Collections with defined iteration order providing positional operations.
744
745
```java { .api }
746
/**
747
* Base interface for collections with defined iteration order
748
*/
749
interface OrderedIterable<T> extends RichIterable<T> {
750
/**
751
* Get first element
752
* @return first element
753
* @throws NoSuchElementException if empty
754
*/
755
T getFirst();
756
757
/**
758
* Get last element
759
* @return last element
760
* @throws NoSuchElementException if empty
761
*/
762
T getLast();
763
764
/**
765
* Find index of object in ordered collection
766
* @param object object to find
767
* @return index of object or -1 if not found
768
*/
769
int indexOf(Object object);
770
771
/**
772
* Get element at index
773
* @param index index to retrieve
774
* @return element at index
775
* @throws IndexOutOfBoundsException if index invalid
776
*/
777
T get(int index);
778
779
// Positional operations
780
/**
781
* Take first N elements
782
* @param count number of elements to take
783
* @return OrderedIterable of first N elements
784
*/
785
OrderedIterable<T> take(int count);
786
787
/**
788
* Drop first N elements
789
* @param count number of elements to drop
790
* @return OrderedIterable without first N elements
791
*/
792
OrderedIterable<T> drop(int count);
793
794
/**
795
* Take elements while predicate is true
796
* @param predicate condition to test elements
797
* @return OrderedIterable of elements taken while condition holds
798
*/
799
OrderedIterable<T> takeWhile(Predicate<? super T> predicate);
800
801
/**
802
* Drop elements while predicate is true
803
* @param predicate condition to test elements
804
* @return OrderedIterable after dropping elements while condition holds
805
*/
806
OrderedIterable<T> dropWhile(Predicate<? super T> predicate);
807
808
/**
809
* Remove consecutive duplicate elements preserving order
810
* @return OrderedIterable with duplicates removed
811
*/
812
OrderedIterable<T> distinct();
813
814
/**
815
* Reverse the order of elements
816
* @return OrderedIterable with reversed order
817
*/
818
OrderedIterable<T> toReversed();
819
820
// Zipping operations
821
/**
822
* Zip with another iterable creating pairs
823
* @param that iterable to zip with
824
* @return OrderedIterable of Pairs
825
*/
826
<S> OrderedIterable<Pair<T, S>> zip(Iterable<S> that);
827
828
/**
829
* Zip with indices creating index-element pairs
830
* @return OrderedIterable of Pairs containing elements and their indices
831
*/
832
OrderedIterable<Pair<T, Integer>> zipWithIndex();
833
}
834
835
/**
836
* Mutable ordered collection
837
*/
838
interface MutableOrderedIterable<T> extends OrderedIterable<T>, MutableCollection<T> {
839
// Mutable positional operations
840
MutableOrderedIterable<T> take(int count);
841
MutableOrderedIterable<T> drop(int count);
842
MutableOrderedIterable<T> takeWhile(Predicate<? super T> predicate);
843
MutableOrderedIterable<T> dropWhile(Predicate<? super T> predicate);
844
MutableOrderedIterable<T> distinct();
845
MutableOrderedIterable<T> toReversed();
846
847
// Mutable zipping
848
<S> MutableOrderedIterable<Pair<T, S>> zip(Iterable<S> that);
849
MutableOrderedIterable<Pair<T, Integer>> zipWithIndex();
850
}
851
```
852
853
**Usage Examples:**
854
855
```java
856
import org.eclipse.collections.impl.factory.Lists;
857
858
MutableList<Integer> numbers = Lists.mutable.with(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
859
860
// Positional operations
861
OrderedIterable<Integer> firstFive = numbers.take(5); // [1, 2, 3, 4, 5]
862
OrderedIterable<Integer> lastFive = numbers.drop(5); // [6, 7, 8, 9, 10]
863
OrderedIterable<Integer> whileLessThan5 = numbers.takeWhile(x -> x < 5); // [1, 2, 3, 4]
864
OrderedIterable<Integer> afterGreaterThan5 = numbers.dropWhile(x -> x <= 5); // [6, 7, 8, 9, 10]
865
866
// Zipping operations
867
List<String> letters = Lists.mutable.with("A", "B", "C", "D", "E");
868
OrderedIterable<Pair<Integer, String>> zipped = numbers.take(5).zip(letters);
869
// [(1,A), (2,B), (3,C), (4,D), (5,E)]
870
871
OrderedIterable<Pair<Integer, Integer>> withIndex = numbers.take(3).zipWithIndex();
872
// [(1,0), (2,1), (3,2)]
873
874
// Distinct operation
875
List<Integer> withDuplicates = Lists.mutable.with(1, 2, 2, 3, 3, 3, 4, 4, 5);
876
OrderedIterable<Integer> uniqueValues = withDuplicates.distinct(); // [1, 2, 3, 4, 5]
877
```
878
879
### Utility Collections and Features
880
881
Additional specialized collection types and features.
882
883
```java { .api }
884
/**
885
* Collection that maintains fixed size after creation
886
* Modification operations that would change size throw UnsupportedOperationException
887
*/
888
interface FixedSizeCollection<T> extends MutableCollection<T> {
889
// Available operations: set, replace, sort, reverse
890
// Not available: add, remove, clear (size-changing operations)
891
}
892
893
/**
894
* Thread-safe collection optimized for multiple readers with single writer
895
*/
896
interface MultiReaderCollection<T> extends MutableCollection<T> {
897
/**
898
* Acquire read lock for thread-safe read operations
899
* @return read lock
900
*/
901
Lock getReadLock();
902
903
/**
904
* Acquire write lock for thread-safe write operations
905
* @return write lock
906
*/
907
Lock getWriteLock();
908
909
/**
910
* Execute read operation with automatic read lock management
911
* @param procedure read operation to perform
912
*/
913
void withReadLockAndDelegate(Procedure<? super MutableCollection<T>> procedure);
914
915
/**
916
* Execute write operation with automatic write lock management
917
* @param procedure write operation to perform
918
*/
919
void withWriteLockAndDelegate(Procedure<? super MutableCollection<T>> procedure);
920
}
921
922
/**
923
* Collection using custom hashing strategy instead of object's hashCode/equals
924
*/
925
interface MutableCollectionWithHashingStrategy<T> extends MutableCollection<T> {
926
/**
927
* Get the hashing strategy used by this collection
928
* @return HashingStrategy instance
929
*/
930
HashingStrategy<? super T> hashingStrategy();
931
}
932
933
/**
934
* Custom hashing and equality strategy interface
935
*/
936
interface HashingStrategy<T> {
937
/**
938
* Compute hash code for object using custom strategy
939
* @param object object to compute hash for
940
* @return hash code
941
*/
942
int computeHashCode(T object);
943
944
/**
945
* Test equality using custom strategy
946
* @param object1 first object
947
* @param object2 second object
948
* @return true if objects are equal according to strategy
949
*/
950
boolean equals(T object1, T object2);
951
}
952
```
953
954
**Usage Examples:**
955
956
```java
957
import org.eclipse.collections.impl.collection.mutable.CollectionAdapter;
958
import org.eclipse.collections.impl.set.strategy.mutable.MutableHashingStrategySet;
959
960
// Fixed-size collections
961
FixedSizeList<String> fixedList = Lists.fixedSize.with("A", "B", "C");
962
// fixedList.add("D"); // Throws UnsupportedOperationException
963
fixedList.set(0, "X"); // OK - doesn't change size
964
965
// Custom hashing strategy for case-insensitive strings
966
HashingStrategy<String> caseInsensitive = new HashingStrategy<String>() {
967
public int computeHashCode(String string) {
968
return string == null ? 0 : string.toLowerCase().hashCode();
969
}
970
971
public boolean equals(String s1, String s2) {
972
return s1 == null ? s2 == null : s1.equalsIgnoreCase(s2);
973
}
974
};
975
976
MutableSet<String> caseInsensitiveSet = new MutableHashingStrategySet<>(caseInsensitive);
977
caseInsensitiveSet.add("Hello");
978
caseInsensitiveSet.add("HELLO"); // Not added - considered duplicate
979
caseInsensitiveSet.add("World");
980
// Set contains: ["Hello", "World"] (case-insensitive duplicates removed)
981
982
// Multi-reader collections for concurrent access
983
MultiReaderList<String> concurrentList = MultiReaderFastList.newList();
984
concurrentList.add("item1");
985
concurrentList.add("item2");
986
987
// Thread-safe read operation
988
concurrentList.withReadLockAndDelegate(list -> {
989
// Perform read operations
990
int size = list.size();
991
boolean contains = list.contains("item1");
992
});
993
994
// Thread-safe write operation
995
concurrentList.withWriteLockAndDelegate(list -> {
996
// Perform write operations
997
list.add("item3");
998
list.remove("item1");
999
});
1000
```
1001
1002
## Integration Patterns
1003
1004
### Converting Between Collection Types
1005
1006
Eclipse Collections provides seamless conversion between different collection types:
1007
1008
```java
1009
// Convert between mutable and immutable
1010
MutableList<String> mutableList = Lists.mutable.with("A", "B", "C");
1011
ImmutableList<String> immutableList = mutableList.toImmutable();
1012
MutableList<String> backToMutable = immutableList.toList();
1013
1014
// Convert between different collection types
1015
MutableSet<String> set = mutableList.toSet();
1016
MutableBag<String> bag = mutableList.toBag();
1017
MutableStack<String> stack = Stacks.mutable.withAll(mutableList);
1018
1019
// Convert to JDK collections
1020
List<String> jdkList = mutableList.castToList();
1021
Set<String> jdkSet = set.castToSet();
1022
Map<String, String> jdkMap = Maps.mutable.with("key1", "value1").castToMap();
1023
1024
// Convert from JDK collections
1025
List<String> jdkSource = Arrays.asList("X", "Y", "Z");
1026
MutableList<String> adapted = ListAdapter.adapt(jdkSource);
1027
MutableList<String> copied = Lists.mutable.withAll(jdkSource);
1028
```
1029
1030
### Performance Optimization Patterns
1031
1032
Use Eclipse Collections features for optimal performance:
1033
1034
```java
1035
// Use primitive collections to avoid boxing
1036
MutableIntList primitiveInts = IntLists.mutable.with(1, 2, 3, 4, 5);
1037
long sum = primitiveInts.sum(); // No boxing
1038
1039
// Use lazy evaluation for large datasets
1040
LazyIterable<String> lazy = hugeMutableList
1041
.asLazy()
1042
.select(expensive::predicate)
1043
.collect(expensive::transformation)
1044
.select(another::predicate);
1045
// Only computed when terminal operation called
1046
MutableList<String> result = lazy.toList();
1047
1048
// Use parallel processing for CPU-intensive operations
1049
MutableList<ComplexObject> processed = hugeList
1050
.asParallel(ForkJoinPool.commonPool(), 1000)
1051
.collect(ComplexObject::expensiveTransformation)
1052
.toList();
1053
1054
// Use immutable collections for thread safety without locks
1055
ImmutableList<String> threadSafeList = Lists.immutable.with("A", "B", "C");
1056
// Can be safely shared across threads without synchronization
1057
```