or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

basic-utilities.mdcaching.mdcollections.mdconcurrency.mdgraph-api.mdhash-math.mdimmutable-collections.mdindex.mdio-utilities.mdother-utilities.md

collections.mddocs/

0

# Collections

1

2

Enhanced collection types and utilities including multimaps, multisets, tables, and powerful collection transformation operations. These utilities extend Java's collection framework with additional data structures and convenient operations.

3

4

## Package: com.google.common.collect

5

6

### Collection Utilities

7

8

Static utility methods for creating and manipulating collections.

9

10

```java { .api }

11

import com.google.common.collect.Lists;

12

import com.google.common.collect.Sets;

13

import com.google.common.collect.Maps;

14

15

// Creating lists

16

List<String> arrayList = Lists.newArrayList("a", "b", "c");

17

List<String> linkedList = Lists.newLinkedList();

18

List<String> withCapacity = Lists.newArrayListWithCapacity(100);

19

20

// List operations

21

List<String> reversed = Lists.reverse(originalList);

22

List<List<String>> partitioned = Lists.partition(list, 3); // Split into chunks of 3

23

List<Character> chars = Lists.charactersOf("hello"); // ['h', 'e', 'l', 'l', 'o']

24

25

// Creating sets

26

Set<String> hashSet = Sets.newHashSet("a", "b", "c");

27

Set<String> linkedHashSet = Sets.newLinkedHashSet();

28

SortedSet<String> treeSet = Sets.newTreeSet();

29

30

// Set operations

31

Set<String> union = Sets.union(set1, set2);

32

Set<String> intersection = Sets.intersection(set1, set2);

33

Set<String> difference = Sets.difference(set1, set2);

34

Set<String> symmetricDifference = Sets.symmetricDifference(set1, set2);

35

36

// Power set (all possible subsets)

37

Set<Set<String>> powerSet = Sets.powerSet(ImmutableSet.of("a", "b", "c"));

38

39

// Creating maps

40

Map<String, Integer> hashMap = Maps.newHashMap();

41

Map<String, Integer> linkedHashMap = Maps.newLinkedHashMap();

42

SortedMap<String, Integer> treeMap = Maps.newTreeMap();

43

ConcurrentMap<String, Integer> concurrentMap = Maps.newConcurrentMap();

44

```

45

46

### Iterables

47

48

Static utility methods for working with Iterable instances. Provides functional-style operations and convenient methods for common iterable manipulations.

49

50

```java { .api }

51

import com.google.common.collect.Iterables;

52

import com.google.common.base.Predicate;

53

import com.google.common.base.Function;

54

55

// Size and containment

56

int size = Iterables.size(iterable);

57

boolean contains = Iterables.contains(iterable, element);

58

int frequency = Iterables.frequency(iterable, element);

59

boolean isEmpty = Iterables.isEmpty(iterable);

60

61

// Element access

62

String first = Iterables.getFirst(iterable, "default");

63

String last = Iterables.getLast(iterable);

64

String element = Iterables.get(iterable, 2); // Get element at index 2

65

String only = Iterables.getOnlyElement(iterable); // Expects exactly one element

66

67

// Filtering and transformation

68

Iterable<String> filtered = Iterables.filter(iterable, new Predicate<String>() {

69

public boolean apply(String s) { return s.startsWith("A"); }

70

});

71

72

Iterable<String> byType = Iterables.filter(objects, String.class);

73

74

Iterable<Integer> transformed = Iterables.transform(strings, new Function<String, Integer>() {

75

public boolean apply(String s) { return s.length(); }

76

});

77

78

// Finding elements

79

String found = Iterables.find(iterable, predicate);

80

String foundOrNull = Iterables.find(iterable, predicate, null);

81

Optional<String> tryFind = Iterables.tryFind(iterable, predicate);

82

int index = Iterables.indexOf(iterable, predicate);

83

84

// Predicates

85

boolean any = Iterables.any(iterable, predicate);

86

boolean all = Iterables.all(iterable, predicate);

87

88

// Combining and partitioning

89

Iterable<String> concatenated = Iterables.concat(iterable1, iterable2, iterable3);

90

Iterable<String> cycled = Iterables.cycle("A", "B", "C"); // Infinite cycle

91

Iterable<List<String>> partitioned = Iterables.partition(iterable, 3);

92

93

// Skipping and limiting

94

Iterable<String> skipped = Iterables.skip(iterable, 5);

95

Iterable<String> limited = Iterables.limit(iterable, 10);

96

97

// Conversion

98

String[] array = Iterables.toArray(iterable, String.class);

99

boolean added = Iterables.addAll(collection, iterable);

100

101

// Comparison and equality

102

boolean equal = Iterables.elementsEqual(iterable1, iterable2);

103

String string = Iterables.toString(iterable);

104

105

// Collection modification

106

boolean removed = Iterables.removeAll(iterable, elementsToRemove);

107

boolean retained = Iterables.retainAll(iterable, elementsToRetain);

108

boolean removedIf = Iterables.removeIf(iterable, predicate);

109

```

110

111

**Key Methods:**

112

- `size(Iterable)` - Returns number of elements

113

- `contains(Iterable, Object)` - Tests if element is present

114

- `getFirst(Iterable, T)` / `getLast(Iterable)` - Get first/last elements

115

- `get(Iterable, int)` - Get element at specific position

116

- `getOnlyElement(Iterable)` - Get single element (throws if not exactly one)

117

- `filter(Iterable, Predicate)` - Filter elements by predicate

118

- `filter(Iterable, Class)` - Filter by type

119

- `transform(Iterable, Function)` - Transform elements

120

- `find(Iterable, Predicate)` - Find first matching element

121

- `tryFind(Iterable, Predicate)` - Find first matching element as Optional

122

- `any(Iterable, Predicate)` / `all(Iterable, Predicate)` - Test predicates

123

- `concat(Iterable...)` - Concatenate multiple iterables

124

- `cycle(T...)` / `cycle(Iterable)` - Create cyclic iterable

125

- `partition(Iterable, int)` - Split into fixed-size chunks

126

- `skip(Iterable, int)` - Skip first N elements

127

- `limit(Iterable, int)` - Limit to first N elements

128

- `elementsEqual(Iterable, Iterable)` - Compare element-wise equality

129

130

### Iterators

131

132

Static utility methods for working with Iterator instances. Companion to Iterables with iterator-specific operations.

133

134

```java { .api }

135

import com.google.common.collect.Iterators;

136

137

// Size and advancement

138

int size = Iterators.size(iterator);

139

boolean advanced = Iterators.advance(iterator, 5); // Skip 5 elements

140

Iterator<T> consumed = Iterators.consumingIterator(iterator);

141

142

// Element access

143

T next = Iterators.getNext(iterator, defaultValue);

144

T last = Iterators.getLast(iterator);

145

T only = Iterators.getOnlyElement(iterator);

146

147

// Filtering and transformation

148

Iterator<String> filtered = Iterators.filter(iterator, predicate);

149

Iterator<String> byType = Iterators.filter(objects, String.class);

150

Iterator<Integer> transformed = Iterators.transform(strings, function);

151

152

// Finding

153

T found = Iterators.find(iterator, predicate);

154

Optional<T> tryFind = Iterators.tryFind(iterator, predicate);

155

int index = Iterators.indexOf(iterator, predicate);

156

157

// Predicates

158

boolean any = Iterators.any(iterator, predicate);

159

boolean all = Iterators.all(iterator, predicate);

160

161

// Combining

162

Iterator<T> concatenated = Iterators.concat(iter1, iter2, iter3);

163

Iterator<T> cycled = Iterators.cycle(list); // Infinite cycle over list

164

Iterator<List<T>> partitioned = Iterators.partition(iterator, batchSize);

165

166

// Limiting and peeking

167

Iterator<T> limited = Iterators.limit(iterator, maxElements);

168

PeekingIterator<T> peeking = Iterators.peekingIterator(iterator);

169

T peeked = peeking.peek(); // Look at next without consuming

170

171

// Conversion

172

List<T> list = Iterators.toList(iterator);

173

T[] array = Iterators.toArray(iterator, clazz);

174

boolean added = Iterators.addAll(collection, iterator);

175

176

// Unmodifiable wrappers

177

Iterator<T> unmodifiable = Iterators.unmodifiableIterator(iterator);

178

ListIterator<T> unmodifiableList = Iterators.unmodifiableListIterator(listIterator);

179

180

// Comparison

181

boolean equal = Iterators.elementsEqual(iter1, iter2);

182

String string = Iterators.toString(iterator);

183

184

// Collection modification

185

int removed = Iterators.removeAll(iterator, elementsToRemove);

186

int retained = Iterators.retainAll(iterator, elementsToRetain);

187

boolean removedIf = Iterators.removeIf(iterator, predicate);

188

```

189

190

**Key Methods:**

191

- `size(Iterator)` - Count remaining elements (consumes iterator)

192

- `advance(Iterator, int)` - Skip N elements

193

- `getNext(Iterator, T)` - Get next element with default

194

- `getLast(Iterator)` - Get last element (consumes iterator)

195

- `filter(Iterator, Predicate)` - Filter by predicate

196

- `transform(Iterator, Function)` - Transform elements

197

- `find(Iterator, Predicate)` - Find first matching element

198

- `concat(Iterator...)` - Concatenate multiple iterators

199

- `cycle(Iterable)` - Create infinite cycling iterator

200

- `partition(Iterator, int)` - Batch elements into lists

201

- `limit(Iterator, int)` - Limit number of elements

202

- `peekingIterator(Iterator)` - Wrap to support peeking

203

- `consumingIterator(Iterator)` - Remove elements as they're accessed

204

- `toList(Iterator)` / `toArray(Iterator, Class)` - Convert to collections

205

206

### Multimap

207

208

A collection that maps keys to multiple values, similar to `Map<K, Collection<V>>` but with a cleaner API.

209

210

```java { .api }

211

import com.google.common.collect.Multimap;

212

import com.google.common.collect.ArrayListMultimap;

213

import com.google.common.collect.HashMultimap;

214

import com.google.common.collect.LinkedHashMultimap;

215

216

// Creating multimaps

217

ListMultimap<String, String> listMultimap = ArrayListMultimap.create();

218

SetMultimap<String, String> setMultimap = HashMultimap.create();

219

SetMultimap<String, String> orderedMultimap = LinkedHashMultimap.create();

220

221

// Adding values

222

listMultimap.put("fruits", "apple");

223

listMultimap.put("fruits", "banana");

224

listMultimap.put("fruits", "apple"); // Duplicates allowed in ListMultimap

225

listMultimap.put("vegetables", "carrot");

226

227

// Retrieving values

228

Collection<String> fruits = listMultimap.get("fruits"); // ["apple", "banana", "apple"]

229

boolean hasFruit = listMultimap.containsKey("fruits"); // true

230

boolean hasApple = listMultimap.containsValue("apple"); // true

231

boolean hasEntry = listMultimap.containsEntry("fruits", "apple"); // true

232

233

// Bulk operations

234

listMultimap.putAll("colors", Arrays.asList("red", "green", "blue"));

235

listMultimap.removeAll("fruits"); // Removes all values for key

236

listMultimap.replaceValues("vegetables", Arrays.asList("carrot", "potato"));

237

238

// Views

239

Set<String> keys = listMultimap.keySet(); // All keys

240

Collection<String> values = listMultimap.values(); // All values

241

Collection<Map.Entry<String, String>> entries = listMultimap.entries(); // All key-value pairs

242

Map<String, Collection<String>> mapView = listMultimap.asMap(); // Map view

243

244

// Size operations

245

int size = listMultimap.size(); // Total number of key-value pairs

246

int keyCount = listMultimap.keySet().size(); // Number of distinct keys

247

boolean empty = listMultimap.isEmpty();

248

```

249

250

**Multimap Implementations:**

251

- `ArrayListMultimap` - Backed by ArrayList for each key (allows duplicate values, preserves order)

252

- `HashMultimap` - Backed by HashSet for each key (no duplicate values, no order guarantees)

253

- `LinkedHashMultimap` - Backed by LinkedHashSet for each key (no duplicates, preserves insertion order)

254

- `TreeMultimap` - Backed by TreeSet for each key (sorted values, no duplicates)

255

256

### Multiset

257

258

A collection that allows duplicate elements and provides count-based operations.

259

260

```java { .api }

261

import com.google.common.collect.Multiset;

262

import com.google.common.collect.HashMultiset;

263

import com.google.common.collect.TreeMultiset;

264

265

// Creating multisets

266

Multiset<String> multiset = HashMultiset.create();

267

Multiset<String> sorted = TreeMultiset.create();

268

269

// Adding elements with counts

270

multiset.add("apple"); // count: 1

271

multiset.add("apple", 5); // count: 6

272

multiset.setCount("banana", 3); // Set absolute count

273

274

// Counting elements

275

int appleCount = multiset.count("apple"); // 6

276

int totalSize = multiset.size(); // Total number of elements (including duplicates)

277

int distinctSize = multiset.elementSet().size(); // Number of distinct elements

278

279

// Removing elements

280

multiset.remove("apple"); // count: 5

281

multiset.remove("apple", 2); // count: 3

282

multiset.setCount("apple", 0); // Remove completely

283

284

// Views

285

Set<String> distinctElements = multiset.elementSet(); // Unique elements

286

Set<Multiset.Entry<String>> entries = multiset.entrySet(); // Element-count pairs

287

288

// Iterating with counts

289

for (Multiset.Entry<String> entry : multiset.entrySet()) {

290

String element = entry.getElement();

291

int count = entry.getCount();

292

System.out.println(element + " appears " + count + " times");

293

}

294

295

// Multiset operations using Multisets utility class

296

import com.google.common.collect.Multisets;

297

298

Multiset<String> intersection = Multisets.intersection(multiset1, multiset2);

299

Multiset<String> union = Multisets.union(multiset1, multiset2);

300

boolean containsAll = Multisets.containsOccurrences(multiset1, multiset2);

301

```

302

303

### BiMap

304

305

A bidirectional map that maintains both key-to-value and value-to-key mappings, ensuring that values are unique.

306

307

```java { .api }

308

import com.google.common.collect.BiMap;

309

import com.google.common.collect.HashBiMap;

310

311

// Creating BiMap

312

BiMap<String, Integer> bimap = HashBiMap.create();

313

314

// Adding entries (values must be unique)

315

bimap.put("one", 1);

316

bimap.put("two", 2);

317

bimap.put("three", 3);

318

319

// Forward mapping

320

Integer value = bimap.get("one"); // 1

321

322

// Inverse mapping

323

BiMap<Integer, String> inverse = bimap.inverse();

324

String key = inverse.get(1); // "one"

325

326

// Forced put (removes existing mappings)

327

bimap.forcePut("four", 1); // Removes "one" -> 1 mapping

328

329

// Handling duplicate values

330

try {

331

bimap.put("four", 2); // Throws IllegalArgumentException (2 already mapped to "two")

332

} catch (IllegalArgumentException e) {

333

// Handle duplicate value

334

}

335

```

336

337

### Table

338

339

A collection similar to `Map<R, Map<C, V>>` but with a cleaner API for two-dimensional data.

340

341

```java { .api }

342

import com.google.common.collect.Table;

343

import com.google.common.collect.HashBasedTable;

344

import com.google.common.collect.TreeBasedTable;

345

import com.google.common.collect.ArrayTable;

346

347

// Creating tables

348

Table<String, String, Integer> table = HashBasedTable.create();

349

Table<String, String, Integer> sortedTable = TreeBasedTable.create();

350

351

// Adding data (row, column, value)

352

table.put("John", "Math", 95);

353

table.put("John", "Science", 87);

354

table.put("Jane", "Math", 92);

355

table.put("Jane", "Science", 94);

356

357

// Retrieving data

358

Integer johnMath = table.get("John", "Math"); // 95

359

boolean hasEntry = table.contains("John", "Math"); // true

360

boolean hasRow = table.containsRow("John"); // true

361

boolean hasColumn = table.containsColumn("Math"); // true

362

363

// Row and column views

364

Map<String, Integer> johnScores = table.row("John"); // {Math=95, Science=87}

365

Map<String, Integer> mathScores = table.column("Math"); // {John=95, Jane=92}

366

367

// All data views

368

Set<String> students = table.rowKeySet(); // [John, Jane]

369

Set<String> subjects = table.columnKeySet(); // [Math, Science]

370

Collection<Integer> allScores = table.values(); // [95, 87, 92, 94]

371

Set<Table.Cell<String, String, Integer>> cells = table.cellSet();

372

373

// Size and operations

374

int size = table.size(); // 4

375

table.remove("John", "Math");

376

table.clear();

377

378

// Array-based table (for dense data with known row/column sets)

379

List<String> students = Arrays.asList("John", "Jane", "Bob");

380

List<String> subjects = Arrays.asList("Math", "Science", "History");

381

Table<String, String, Integer> arrayTable = ArrayTable.create(students, subjects);

382

```

383

384

### Range

385

386

Immutable ranges of Comparable values with various boundary types.

387

388

```java { .api }

389

import com.google.common.collect.Range;

390

import com.google.common.collect.RangeSet;

391

import com.google.common.collect.TreeRangeSet;

392

393

// Creating ranges

394

Range<Integer> open = Range.open(1, 5); // (1, 5) - excludes endpoints

395

Range<Integer> closed = Range.closed(1, 5); // [1, 5] - includes endpoints

396

Range<Integer> openClosed = Range.openClosed(1, 5); // (1, 5]

397

Range<Integer> closedOpen = Range.closedOpen(1, 5); // [1, 5)

398

399

// Unbounded ranges

400

Range<Integer> atLeast = Range.atLeast(5); // [5, +∞)

401

Range<Integer> lessThan = Range.lessThan(5); // (-∞, 5)

402

Range<Integer> greaterThan = Range.greaterThan(5); // (5, +∞)

403

Range<Integer> atMost = Range.atMost(5); // (-∞, 5]

404

Range<Integer> all = Range.all(); // (-∞, +∞)

405

406

// Range operations

407

boolean contains = closed.contains(3); // true

408

boolean encloses = Range.closed(1, 10).encloses(Range.closed(2, 8)); // true

409

410

// Range intersection and span

411

Range<Integer> intersection = Range.closed(1, 5).intersection(Range.closed(3, 7)); // [3, 5]

412

Range<Integer> span = Range.closed(1, 3).span(Range.closed(5, 7)); // [1, 7]

413

414

// Range sets - collection of non-overlapping ranges

415

RangeSet<Integer> rangeSet = TreeRangeSet.create();

416

rangeSet.add(Range.closed(1, 10));

417

rangeSet.add(Range.closed(15, 20));

418

rangeSet.remove(Range.open(5, 7));

419

// Result: [1, 5] ∪ [7, 10] ∪ [15, 20]

420

421

boolean inSet = rangeSet.contains(6); // false

422

RangeSet<Integer> complement = rangeSet.complement();

423

```

424

425

### Iterables and Iterators

426

427

Powerful utilities for working with Iterable and Iterator objects.

428

429

```java { .api }

430

import com.google.common.collect.Iterables;

431

import com.google.common.collect.Iterators;

432

import com.google.common.base.Predicate;

433

import com.google.common.base.Function;

434

435

// Concatenation

436

Iterable<String> combined = Iterables.concat(list1, list2, list3);

437

438

// Transformation

439

Iterable<Integer> lengths = Iterables.transform(strings, new Function<String, Integer>() {

440

public Integer apply(String input) {

441

return input.length();

442

}

443

});

444

445

// Filtering

446

Predicate<String> notEmpty = new Predicate<String>() {

447

public boolean apply(String input) {

448

return !input.isEmpty();

449

}

450

};

451

Iterable<String> filtered = Iterables.filter(strings, notEmpty);

452

453

// Finding elements

454

String first = Iterables.find(strings, notEmpty); // First matching element

455

Optional<String> found = Iterables.tryFind(strings, notEmpty); // Optional result

456

457

// Size and emptiness

458

int size = Iterables.size(iterable); // Works with any Iterable

459

boolean empty = Iterables.isEmpty(iterable);

460

461

// Element access

462

String first = Iterables.getFirst(strings, "default");

463

String last = Iterables.getLast(strings, "default");

464

String third = Iterables.get(strings, 2, "default"); // Index-based access

465

466

// Limiting and skipping

467

Iterable<String> limited = Iterables.limit(strings, 10); // First 10 elements

468

Iterable<String> skipped = Iterables.skip(strings, 5); // Skip first 5 elements

469

470

// Cycling and partitioning

471

Iterable<String> cycled = Iterables.cycle(strings); // Infinite repetition

472

Iterable<List<String>> partitioned = Iterables.partition(strings, 3); // Groups of 3

473

474

// Similar operations available for Iterators

475

Iterator<String> concatenated = Iterators.concat(iter1, iter2);

476

Iterator<Integer> transformed = Iterators.transform(stringIter, lengthFunction);

477

Iterator<String> filtered2 = Iterators.filter(stringIter, predicate);

478

```

479

480

### Map Utilities

481

482

Advanced map operations including transformations, filtering, and specialized map types.

483

484

```java { .api }

485

import com.google.common.collect.Maps;

486

import com.google.common.collect.MapDifference;

487

488

// Map transformation

489

Map<String, String> upperCaseKeys = Maps.transformKeys(originalMap,

490

new Function<String, String>() {

491

public String apply(String key) {

492

return key.toUpperCase();

493

}

494

});

495

496

Map<String, Integer> lengthValues = Maps.transformValues(stringMap,

497

new Function<String, Integer>() {

498

public Integer apply(String value) {

499

return value.length();

500

}

501

});

502

503

// Map filtering

504

Map<String, Integer> filteredByKeys = Maps.filterKeys(map,

505

new Predicate<String>() {

506

public boolean apply(String key) {

507

return key.startsWith("a");

508

}

509

});

510

511

Map<String, Integer> filteredByValues = Maps.filterValues(map,

512

new Predicate<Integer>() {

513

public boolean apply(Integer value) {

514

return value > 10;

515

}

516

});

517

518

// Map differences

519

Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);

520

Map<String, Integer> right = ImmutableMap.of("a", 1, "b", 4, "d", 5);

521

MapDifference<String, Integer> diff = Maps.difference(left, right);

522

523

Map<String, Integer> entriesOnlyOnLeft = diff.entriesOnlyOnLeft(); // {c=3}

524

Map<String, Integer> entriesOnlyOnRight = diff.entriesOnlyOnRight(); // {d=5}

525

Map<String, Integer> entriesInCommon = diff.entriesInCommon(); // {a=1}

526

Map<String, MapDifference.ValueDifference<Integer>> entriesDiffering = diff.entriesDiffering(); // {b=(2, 4)}

527

528

// Creating map from properties

529

Properties props = new Properties();

530

Map<String, String> mapFromProps = Maps.fromProperties(props);

531

```

532

533

### Advanced Collection Operations

534

535

```java { .api }

536

import com.google.common.collect.Collections2;

537

import com.google.common.collect.Ordering;

538

539

// Collection transformation and filtering

540

Collection<Integer> lengths = Collections2.transform(strings, lengthFunction);

541

Collection<String> filtered = Collections2.filter(strings, notEmptyPredicate);

542

543

// Permutations

544

Collection<List<String>> permutations = Collections2.permutations(Arrays.asList("a", "b", "c"));

545

// Results in: [[a,b,c], [a,c,b], [b,a,c], [b,c,a], [c,a,b], [c,b,a]]

546

547

// Ordering (comparator utilities)

548

Ordering<String> byLength = Ordering.natural().onResultOf(new Function<String, Integer>() {

549

public Integer apply(String input) {

550

return input.length();

551

}

552

});

553

554

List<String> sorted = byLength.sortedCopy(strings);

555

String min = byLength.min(strings);

556

String max = byLength.max(strings);

557

List<String> greatest = byLength.greatestOf(strings, 3);

558

List<String> least = byLength.leastOf(strings, 3);

559

560

// Compound ordering

561

Ordering<Person> byAgeThemByName = Ordering.natural()

562

.onResultOf(new Function<Person, Integer>() {

563

public Integer apply(Person p) { return p.getAge(); }

564

})

565

.compound(Ordering.natural().onResultOf(new Function<Person, String>() {

566

public String apply(Person p) { return p.getName(); }

567

}));

568

```

569

570

### Synchronized and Concurrent Collections

571

572

```java { .api }

573

import com.google.common.collect.Multimaps;

574

import com.google.common.collect.Multisets;

575

import com.google.common.collect.Tables;

576

577

// Synchronized wrappers

578

Multimap<String, String> syncMultimap = Multimaps.synchronizedMultimap(multimap);

579

Multiset<String> syncMultiset = Multisets.synchronizedMultiset(multiset);

580

Table<String, String, Integer> syncTable = Tables.synchronizedTable(table);

581

582

// Unmodifiable views

583

Multimap<String, String> unmodifiableMultimap = Multimaps.unmodifiableMultimap(multimap);

584

Multiset<String> unmodifiableMultiset = Multisets.unmodifiableMultiset(multiset);

585

586

// Creating multimaps from existing maps

587

Map<String, String> existingMap = Maps.newHashMap();

588

Multimap<String, String> multimapFromMap = Multimaps.forMap(existingMap);

589

590

// Index operations - creating multimaps by indexing collections

591

List<String> words = Arrays.asList("apple", "banana", "apricot", "blueberry");

592

Multimap<Character, String> byFirstLetter = Multimaps.index(words,

593

new Function<String, Character>() {

594

public Character apply(String word) {

595

return word.charAt(0);

596

}

597

});

598

// Result: {a=[apple, apricot], b=[banana, blueberry]}

599

```

600

601

### Additional Collection Implementations

602

603

Specialized collection implementations for specific use cases.

604

605

```java { .api }

606

import com.google.common.collect.ArrayTable;

607

import com.google.common.collect.Collections2;

608

import com.google.common.collect.Ordering;

609

610

// Array-based table for dense data with known dimensions

611

List<String> rowKeys = Arrays.asList("Q1", "Q2", "Q3", "Q4");

612

List<String> columnKeys = Arrays.asList("Sales", "Marketing", "Engineering");

613

614

ArrayTable<String, String, Integer> quarterlyBudget = ArrayTable.create(rowKeys, columnKeys);

615

quarterlyBudget.put("Q1", "Sales", 100000);

616

quarterlyBudget.put("Q1", "Marketing", 50000);

617

quarterlyBudget.put("Q1", "Engineering", 200000);

618

619

// Efficient access by index

620

Integer q1Sales = quarterlyBudget.at(0, 0); // Q1 Sales budget

621

Map<String, Integer> q1Budget = quarterlyBudget.row("Q1");

622

623

// Collections2 utilities for collection transformation

624

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

625

626

// Transform collection (creates a view, not a copy)

627

Collection<String> upperCase = Collections2.transform(names,

628

new Function<String, String>() {

629

public String apply(String name) {

630

return name.toUpperCase();

631

}

632

});

633

634

// Filter collection (creates a view, not a copy)

635

Collection<String> longNames = Collections2.filter(names,

636

new Predicate<String>() {

637

public boolean apply(String name) {

638

return name.length() > 4;

639

}

640

});

641

642

// Generate permutations

643

Collection<List<String>> permutations = Collections2.permutations(

644

Arrays.asList("A", "B", "C"));

645

// Results in all 6 permutations: [A,B,C], [A,C,B], [B,A,C], etc.

646

647

// Ordering utilities (enhanced comparator)

648

Ordering<String> byLength = Ordering.natural().onResultOf(

649

new Function<String, Integer>() {

650

public Integer apply(String s) {

651

return s.length();

652

}

653

});

654

655

// Use ordering for various operations

656

List<String> words = Arrays.asList("elephant", "cat", "hippopotamus", "dog");

657

List<String> sortedByLength = byLength.sortedCopy(words); // [cat, dog, elephant, hippopotamus]

658

String shortest = byLength.min(words); // "cat"

659

String longest = byLength.max(words); // "hippopotamus"

660

661

// Get top/bottom N elements

662

List<String> shortest3 = byLength.leastOf(words, 3); // [cat, dog, elephant]

663

List<String> longest2 = byLength.greatestOf(words, 2); // [hippopotamus, elephant]

664

665

// Null-safe ordering

666

Ordering<String> nullsFirst = Ordering.natural().nullsFirst();

667

Ordering<String> nullsLast = Ordering.natural().nullsLast();

668

669

// Compound ordering (multiple criteria)

670

Ordering<Person> byAgeThemName = Ordering.natural()

671

.onResultOf(new Function<Person, Integer>() {

672

public Integer apply(Person p) { return p.getAge(); }

673

})

674

.compound(Ordering.natural().onResultOf(new Function<Person, String>() {

675

public String apply(Person p) { return p.getName(); }

676

}));

677

```

678

679

**Additional Collection Classes:**

680

681

- `ArrayTable<R,C,V>` - Table implementation backed by a 2D array, optimized for dense data

682

- `Collections2` - Static utility methods for creating transformed views of collections

683

- `Ordering<T>` - Enhanced comparator with fluent API for sorting and selection operations

684

685

This collections framework provides powerful abstractions that extend Java's standard collections with specialized data structures optimized for common use cases, comprehensive utility methods for transformation and manipulation, and convenient APIs that reduce boilerplate code while maintaining type safety and performance.