or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

classfile-builder.mdclassfile.mdindex.mdmemoize.mdpreview.mdresult.mdsignatures.mdstream.mdunmodifiable.md

unmodifiable.mddocs/

0

# Immutable Collections

1

2

Thread-safe, unmodifiable collection implementations with factory methods compatible with Java 9+ collection APIs but available for earlier Java versions. This package provides high-performance immutable collections that ensure data integrity and thread safety.

3

4

## Capabilities

5

6

### Immutable Lists

7

8

Create and manipulate immutable lists with various factory methods and guaranteed thread safety.

9

10

```java { .api }

11

/**

12

* Factory methods for creating immutable lists

13

*/

14

public final class Lists {

15

/**

16

* Create an empty immutable list

17

* @return Empty immutable list

18

*/

19

public static <E> List<E> of();

20

21

/**

22

* Create an immutable list with one element

23

* @param element The single element

24

* @return Immutable list containing the element

25

*/

26

public static <E> List<E> of(E element);

27

28

/**

29

* Create an immutable list with two elements

30

* @param e1 First element

31

* @param e2 Second element

32

* @return Immutable list containing the elements

33

*/

34

public static <E> List<E> of(E e1, E e2);

35

36

/**

37

* Create an immutable list with three elements

38

* @param e1 First element

39

* @param e2 Second element

40

* @param e3 Third element

41

* @return Immutable list containing the elements

42

*/

43

public static <E> List<E> of(E e1, E e2, E e3);

44

45

/**

46

* Create an immutable list with four elements

47

* @param e1 First element

48

* @param e2 Second element

49

* @param e3 Third element

50

* @param e4 Fourth element

51

* @return Immutable list containing the elements

52

*/

53

public static <E> List<E> of(E e1, E e2, E e3, E e4);

54

55

/**

56

* Create an immutable list with five elements

57

* @param e1 First element

58

* @param e2 Second element

59

* @param e3 Third element

60

* @param e4 Fourth element

61

* @param e5 Fifth element

62

* @return Immutable list containing the elements

63

*/

64

public static <E> List<E> of(E e1, E e2, E e3, E e4, E e5);

65

66

/**

67

* Create an immutable list from variable arguments

68

* @param elements Variable number of elements

69

* @return Immutable list containing the elements

70

*/

71

@SafeVarargs

72

public static <E> List<E> of(E... elements);

73

74

/**

75

* Create an immutable list by copying from an existing collection

76

* @param collection Source collection to copy from

77

* @return Immutable list containing all elements from the collection

78

* @throws NullPointerException if collection is null

79

*/

80

public static <E> List<E> copyOf(Collection<? extends E> collection);

81

82

/**

83

* Collector to create immutable lists from streams

84

* @return Collector that accumulates to an immutable list

85

*/

86

public static <E> Collector<E, ?, List<E>> toList();

87

}

88

```

89

90

**Usage Example:**

91

92

```java

93

import aQute.bnd.unmodifiable.Lists;

94

import java.util.List;

95

import java.util.stream.Stream;

96

97

// Create immutable lists

98

List<String> empty = Lists.of();

99

List<String> single = Lists.of("hello");

100

List<String> multiple = Lists.of("alpha", "beta", "gamma");

101

List<Integer> numbers = Lists.of(1, 2, 3, 4, 5);

102

103

// Copy from existing collection

104

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

105

List<String> immutableCopy = Lists.copyOf(originalList);

106

107

// Use with streams

108

List<String> processed = Stream.of("HELLO", "WORLD", "JAVA")

109

.map(String::toLowerCase)

110

.collect(Lists.toList());

111

112

// Attempt to modify throws UnsupportedOperationException

113

try {

114

multiple.add("delta"); // This will throw

115

} catch (UnsupportedOperationException e) {

116

System.out.println("Cannot modify immutable list");

117

}

118

119

// Safe iteration (no concurrent modification concerns)

120

for (String item : multiple) {

121

System.out.println(item); // Thread-safe iteration

122

}

123

```

124

125

### Immutable Maps

126

127

Create and manipulate immutable maps with type safety and performance optimization.

128

129

```java { .api }

130

/**

131

* Factory methods for creating immutable maps

132

*/

133

public final class Maps {

134

/**

135

* Create an empty immutable map

136

* @return Empty immutable map

137

*/

138

public static <K, V> Map<K, V> of();

139

140

/**

141

* Create an immutable map with one key-value pair

142

* @param key The key

143

* @param value The value

144

* @return Immutable map containing the entry

145

*/

146

public static <K, V> Map<K, V> of(K key, V value);

147

148

/**

149

* Create an immutable map with two key-value pairs

150

* @param k1 First key

151

* @param v1 First value

152

* @param k2 Second key

153

* @param v2 Second value

154

* @return Immutable map containing the entries

155

*/

156

public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2);

157

158

/**

159

* Create an immutable map with three key-value pairs

160

* @param k1 First key

161

* @param v1 First value

162

* @param k2 Second key

163

* @param v2 Second value

164

* @param k3 Third key

165

* @param v3 Third value

166

* @return Immutable map containing the entries

167

*/

168

public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3);

169

170

/**

171

* Create an immutable map with four key-value pairs

172

* @param k1 First key

173

* @param v1 First value

174

* @param k2 Second key

175

* @param v2 Second value

176

* @param k3 Third key

177

* @param v3 Third value

178

* @param k4 Fourth key

179

* @param v4 Fourth value

180

* @return Immutable map containing the entries

181

*/

182

public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4);

183

184

/**

185

* Create an immutable map with five key-value pairs

186

* @param k1 First key

187

* @param v1 First value

188

* @param k2 Second key

189

* @param v2 Second value

190

* @param k3 Third key

191

* @param v3 Third value

192

* @param k4 Fourth key

193

* @param v4 Fourth value

194

* @param k5 Fifth key

195

* @param v5 Fifth value

196

* @return Immutable map containing the entries

197

*/

198

public static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5);

199

200

/**

201

* Create an immutable map from variable map entries

202

* @param entries Variable number of map entries

203

* @return Immutable map containing the entries

204

* @throws IllegalArgumentException if duplicate keys are found

205

*/

206

@SafeVarargs

207

public static <K, V> Map<K, V> ofEntries(Map.Entry<? extends K, ? extends V>... entries);

208

209

/**

210

* Create an immutable map by copying from an existing map

211

* @param map Source map to copy from

212

* @return Immutable map containing all entries from the source map

213

* @throws NullPointerException if map is null

214

*/

215

public static <K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map);

216

217

/**

218

* Create a map entry (convenience method for use with ofEntries)

219

* @param key The key

220

* @param value The value

221

* @return Immutable map entry

222

*/

223

public static <K, V> Map.Entry<K, V> entry(K key, V value);

224

}

225

```

226

227

**Usage Example:**

228

229

```java

230

import aQute.bnd.unmodifiable.Maps;

231

import java.util.Map;

232

233

// Create immutable maps

234

Map<String, Integer> empty = Maps.of();

235

Map<String, Integer> single = Maps.of("one", 1);

236

Map<String, Integer> multiple = Maps.of(

237

"alpha", 1,

238

"beta", 2,

239

"gamma", 3

240

);

241

242

// Create using entries

243

Map<String, String> config = Maps.ofEntries(

244

Maps.entry("host", "localhost"),

245

Maps.entry("port", "8080"),

246

Maps.entry("timeout", "30000")

247

);

248

249

// Copy from existing map

250

Map<String, Integer> originalMap = new HashMap<>();

251

originalMap.put("x", 10);

252

originalMap.put("y", 20);

253

Map<String, Integer> immutableCopy = Maps.copyOf(originalMap);

254

255

// Attempt to modify throws UnsupportedOperationException

256

try {

257

multiple.put("delta", 4); // This will throw

258

} catch (UnsupportedOperationException e) {

259

System.out.println("Cannot modify immutable map");

260

}

261

262

// Safe concurrent access

263

multiple.forEach((key, value) -> {

264

System.out.println(key + " = " + value); // Thread-safe iteration

265

});

266

```

267

268

### Immutable Sets

269

270

Create and manipulate immutable sets with guaranteed uniqueness and performance optimization.

271

272

```java { .api }

273

/**

274

* Factory methods for creating immutable sets

275

*/

276

public final class Sets {

277

/**

278

* Create an empty immutable set

279

* @return Empty immutable set

280

*/

281

public static <E> Set<E> of();

282

283

/**

284

* Create an immutable set with one element

285

* @param element The single element

286

* @return Immutable set containing the element

287

*/

288

public static <E> Set<E> of(E element);

289

290

/**

291

* Create an immutable set with two elements

292

* @param e1 First element

293

* @param e2 Second element

294

* @return Immutable set containing the elements

295

* @throws IllegalArgumentException if duplicate elements are provided

296

*/

297

public static <E> Set<E> of(E e1, E e2);

298

299

/**

300

* Create an immutable set with three elements

301

* @param e1 First element

302

* @param e2 Second element

303

* @param e3 Third element

304

* @return Immutable set containing the elements

305

* @throws IllegalArgumentException if duplicate elements are provided

306

*/

307

public static <E> Set<E> of(E e1, E e2, E e3);

308

309

/**

310

* Create an immutable set with four elements

311

* @param e1 First element

312

* @param e2 Second element

313

* @param e3 Third element

314

* @param e4 Fourth element

315

* @return Immutable set containing the elements

316

* @throws IllegalArgumentException if duplicate elements are provided

317

*/

318

public static <E> Set<E> of(E e1, E e2, E e3, E e4);

319

320

/**

321

* Create an immutable set with five elements

322

* @param e1 First element

323

* @param e2 Second element

324

* @param e3 Third element

325

* @param e4 Fourth element

326

* @param e5 Fifth element

327

* @return Immutable set containing the elements

328

* @throws IllegalArgumentException if duplicate elements are provided

329

*/

330

public static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5);

331

332

/**

333

* Create an immutable set from variable arguments

334

* @param elements Variable number of elements

335

* @return Immutable set containing unique elements

336

* @throws IllegalArgumentException if duplicate elements are provided

337

*/

338

@SafeVarargs

339

public static <E> Set<E> of(E... elements);

340

341

/**

342

* Create an immutable set by copying from an existing collection

343

* @param collection Source collection to copy from

344

* @return Immutable set containing all unique elements from the collection

345

* @throws NullPointerException if collection is null

346

*/

347

public static <E> Set<E> copyOf(Collection<? extends E> collection);

348

349

/**

350

* Collector to create immutable sets from streams

351

* @return Collector that accumulates to an immutable set

352

*/

353

public static <E> Collector<E, ?, Set<E>> toSet();

354

}

355

```

356

357

**Usage Example:**

358

359

```java

360

import aQute.bnd.unmodifiable.Sets;

361

import java.util.Set;

362

import java.util.stream.Stream;

363

364

// Create immutable sets

365

Set<String> empty = Sets.of();

366

Set<String> single = Sets.of("unique");

367

Set<String> multiple = Sets.of("alpha", "beta", "gamma");

368

Set<Integer> numbers = Sets.of(1, 2, 3, 4, 5);

369

370

// Copy from existing collection (removes duplicates)

371

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

372

Set<String> uniqueSet = Sets.copyOf(listWithDuplicates); // Contains: a, b, c

373

374

// Use with streams to remove duplicates

375

Set<String> processed = Stream.of("HELLO", "WORLD", "HELLO", "JAVA")

376

.map(String::toLowerCase)

377

.collect(Sets.toSet()); // Contains: hello, world, java

378

379

// Duplicate detection at creation time

380

try {

381

Set<String> invalid = Sets.of("a", "b", "a"); // This will throw

382

} catch (IllegalArgumentException e) {

383

System.out.println("Duplicate elements not allowed");

384

}

385

386

// Efficient membership testing

387

boolean containsAlpha = multiple.contains("alpha"); // O(1) lookup

388

```

389

390

### Immutable Collection Implementations

391

392

The underlying implementations provide specific guarantees and optimizations.

393

394

```java { .api }

395

/**

396

* Immutable list implementation with guaranteed thread safety

397

*/

398

public class ImmutableList<E> implements List<E> {

399

// All mutating operations throw UnsupportedOperationException

400

// Thread-safe for concurrent read access

401

// Optimized for memory usage and performance

402

}

403

404

/**

405

* Immutable map implementation with guaranteed thread safety

406

*/

407

public class ImmutableMap<K, V> implements Map<K, V> {

408

// All mutating operations throw UnsupportedOperationException

409

// Thread-safe for concurrent read access

410

// Optimized hash table implementation

411

}

412

413

/**

414

* Immutable set implementation with guaranteed thread safety

415

*/

416

public class ImmutableSet<E> implements Set<E> {

417

// All mutating operations throw UnsupportedOperationException

418

// Thread-safe for concurrent read access

419

// Optimized for fast membership testing

420

}

421

422

/**

423

* Immutable map entry implementation

424

*/

425

public class ImmutableEntry<K, V> implements Map.Entry<K, V> {

426

/**

427

* Get the key (never null if key was non-null at creation)

428

*/

429

@Override

430

public K getKey();

431

432

/**

433

* Get the value (may be null if value was null at creation)

434

*/

435

@Override

436

public V getValue();

437

438

/**

439

* Attempt to set value (always throws UnsupportedOperationException)

440

*/

441

@Override

442

public V setValue(V value); // Always throws

443

}

444

```

445

446

### Stream Integration

447

448

Seamless integration with Java 8 streams for functional programming patterns.

449

450

```java { .api }

451

// Collectors are provided for stream termination

452

List<String> immutableList = stream.collect(Lists.toList());

453

Set<String> immutableSet = stream.collect(Sets.toSet());

454

455

// Custom collectors can be built for maps

456

Collector<Person, ?, Map<String, Integer>> toNameAgeMap =

457

Collector.of(

458

HashMap::new,

459

(map, person) -> map.put(person.getName(), person.getAge()),

460

(map1, map2) -> { map1.putAll(map2); return map1; },

461

Maps::copyOf

462

);

463

```

464

465

**Usage Example:**

466

467

```java

468

// Process data with streams and collect to immutable collections

469

List<String> processedList = rawData.stream()

470

.filter(Objects::nonNull)

471

.map(String::trim)

472

.filter(s -> !s.isEmpty())

473

.map(String::toLowerCase)

474

.distinct()

475

.sorted()

476

.collect(Lists.toList());

477

478

Set<String> uniqueWords = text.stream()

479

.flatMap(line -> Arrays.stream(line.split("\\s+")))

480

.map(word -> word.replaceAll("[^a-zA-Z]", ""))

481

.filter(word -> !word.isEmpty())

482

.collect(Sets.toSet());

483

```

484

485

### Performance Characteristics

486

487

The immutable collections are optimized for different use cases:

488

489

**Lists:**

490

- **Random Access**: O(1) for get operations

491

- **Memory Overhead**: Minimal - array-based storage

492

- **Creation Cost**: O(n) copying cost, then immutable

493

- **Iteration**: High performance, no synchronization needed

494

495

**Maps:**

496

- **Lookup**: O(1) average case hash table lookup

497

- **Memory Overhead**: Hash table overhead plus immutability guarantees

498

- **Creation Cost**: O(n) for copying and hash computation

499

- **Iteration**: Efficient key, value, and entry iteration

500

501

**Sets:**

502

- **Membership Testing**: O(1) average case

503

- **Memory Overhead**: Hash set overhead

504

- **Creation Cost**: O(n) with duplicate detection

505

- **Iteration**: Efficient element iteration

506

507

### Thread Safety Guarantees

508

509

All immutable collections provide strong thread safety guarantees:

510

511

1. **No Synchronization Required**: Multiple threads can safely read concurrently

512

2. **No Defensive Copying**: Collections never change, so references can be shared freely

513

3. **Safe Publication**: Once constructed, can be safely published to other threads

514

4. **Iterator Safety**: Iterators never throw ConcurrentModificationException

515

5. **Memory Visibility**: All threads see the same consistent state

516

517

### Comparison with Standard Collections

518

519

**vs ArrayList/HashMap/HashSet:**

520

- Immutable collections prevent accidental modification

521

- Thread-safe without synchronization overhead

522

- Can be safely cached and reused

523

- Eliminate defensive copying needs

524

525

**vs Collections.unmodifiableList/Map/Set:**

526

- True immutability (not just unmodifiable views)

527

- Better performance for read operations

528

- No risk of underlying collection modification

529

- Optimized implementations

530

531

**vs Guava ImmutableList/Map/Set:**

532

- Similar functionality and guarantees

533

- Reduced dependency footprint

534

- Consistent API with Java 9+ collection factories

535

- OSGi-friendly packaging

536

537

### Best Practices

538

539

1. **Prefer Small Collections**: Factory methods are optimized for small collections (≤5 elements)

540

2. **Use copyOf for Large Collections**: More efficient than of(...) for many elements

541

3. **Cache Expensive Results**: Immutable collections are perfect for caching

542

4. **Return Immutable Collections**: From public APIs to prevent external modification

543

5. **Stream Integration**: Use provided collectors for clean functional style

544

6. **Null Handling**: Collections accept null values but not null keys (maps)

545

546

### Migration from Mutable Collections

547

548

```java

549

// Before: Mutable collections requiring defensive copying

550

public List<String> getItems() {

551

return new ArrayList<>(this.items); // Defensive copy

552

}

553

554

// After: Return immutable collection directly

555

public List<String> getItems() {

556

return this.items; // Already immutable, no copying needed

557

}

558

559

// Before: Synchronized access to shared collections

560

private final List<String> items = Collections.synchronizedList(new ArrayList<>());

561

562

// After: Build once, share safely

563

private final List<String> items = Lists.copyOf(buildInitialItems());

564

```

565

566

This approach eliminates many common threading issues and simplifies concurrent programming by making data immutable by default.