or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

array-utilities.mdbuilders.mdconcurrent-utilities.mddate-time-utilities.mdexception-utilities.mdindex.mdmath-utilities.mdobject-utilities.mdstring-utilities.mdvalidation-utilities.md

builders.mddocs/

0

# Builder Utilities

1

2

Apache Commons Lang provides powerful builder pattern utilities that simplify the creation of equals(), hashCode(), toString(), and compareTo() methods. These builders follow fluent interfaces and handle complex cases including null values, arrays, and nested objects automatically.

3

4

## Core Builder Classes

5

6

### ToStringBuilder - Fluent toString() Construction

7

8

Creates readable string representations of objects with extensive customization options:

9

10

```java { .api }

11

import org.apache.commons.lang3.builder.ToStringBuilder;

12

import org.apache.commons.lang3.builder.ToStringStyle;

13

```

14

15

#### Basic Usage

16

17

```java { .api }

18

public class Person {

19

private String name;

20

private int age;

21

private List<String> hobbies;

22

23

@Override

24

public String toString() {

25

return new ToStringBuilder(this)

26

.append("name", name)

27

.append("age", age)

28

.append("hobbies", hobbies)

29

.toString();

30

}

31

}

32

33

// Output: Person@1a2b3c4d[name=John Doe,age=25,hobbies=[reading, gaming]]

34

```

35

36

#### ToStringBuilder Methods

37

38

```java { .api }

39

// Basic field appending

40

public ToStringBuilder append(String fieldName, Object obj)

41

public ToStringBuilder append(String fieldName, boolean value)

42

public ToStringBuilder append(String fieldName, byte value)

43

public ToStringBuilder append(String fieldName, char value)

44

public ToStringBuilder append(String fieldName, double value)

45

public ToStringBuilder append(String fieldName, float value)

46

public ToStringBuilder append(String fieldName, int value)

47

public ToStringBuilder append(String fieldName, long value)

48

public ToStringBuilder append(String fieldName, short value)

49

50

// Array appending

51

public ToStringBuilder append(String fieldName, Object[] array)

52

public ToStringBuilder append(String fieldName, boolean[] array)

53

public ToStringBuilder append(String fieldName, byte[] array)

54

// ... similar for other primitive arrays

55

56

// Advanced appending

57

public ToStringBuilder appendAsObjectToString(Object object)

58

public ToStringBuilder appendSuper(String superToString)

59

public ToStringBuilder appendToString(String toString)

60

```

61

62

#### ToStringStyle Options

63

64

```java { .api }

65

// Predefined styles

66

ToStringStyle.DEFAULT_STYLE // ClassName@hashcode[field=value,field=value]

67

ToStringStyle.MULTI_LINE_STYLE // Each field on separate line

68

ToStringStyle.NO_FIELD_NAMES_STYLE // Values without field names

69

ToStringStyle.SHORT_PREFIX_STYLE // ClassName[field=value,field=value]

70

ToStringStyle.SIMPLE_STYLE // field=value,field=value

71

ToStringStyle.NO_CLASS_NAME_STYLE // [field=value,field=value]

72

ToStringStyle.JSON_STYLE // {"field":"value","field":"value"}

73

```

74

75

**Usage Examples:**

76

```java { .api }

77

public class Employee {

78

private String name = "John Doe";

79

private int id = 12345;

80

private String[] skills = {"Java", "Python", "SQL"};

81

private Address address = new Address("123 Main St", "New York");

82

83

// Default style

84

public String toString() {

85

return new ToStringBuilder(this)

86

.append("name", name)

87

.append("id", id)

88

.append("skills", skills)

89

.append("address", address)

90

.toString();

91

}

92

// Output: Employee@1a2b3c4d[name=John Doe,id=12345,skills={Java,Python,SQL},address=Address@5f6g7h8i[...]]

93

94

// JSON style

95

public String toJsonString() {

96

return new ToStringBuilder(this, ToStringStyle.JSON_STYLE)

97

.append("name", name)

98

.append("id", id)

99

.append("skills", skills)

100

.toString();

101

}

102

// Output: {"name":"John Doe","id":12345,"skills":["Java","Python","SQL"]}

103

104

// Multi-line style

105

public String toMultiLineString() {

106

return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)

107

.append("name", name)

108

.append("id", id)

109

.append("skills", skills)

110

.toString();

111

}

112

// Output:

113

// Employee@1a2b3c4d[

114

// name=John Doe

115

// id=12345

116

// skills={Java,Python,SQL}

117

// ]

118

119

// No field names style

120

public String toSimpleString() {

121

return new ToStringBuilder(this, ToStringStyle.NO_FIELD_NAMES_STYLE)

122

.append(name)

123

.append(id)

124

.append(skills)

125

.toString();

126

}

127

// Output: Employee@1a2b3c4d[John Doe,12345,{Java,Python,SQL}]

128

}

129

```

130

131

#### ReflectionToStringBuilder - Automatic toString()

132

133

Automatically generates toString() using reflection:

134

135

```java { .api }

136

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;

137

138

public class Product {

139

private String name = "Laptop";

140

private double price = 999.99;

141

private boolean inStock = true;

142

143

@Override

144

public String toString() {

145

return ReflectionToStringBuilder.toString(this);

146

}

147

// Automatically includes all fields

148

149

// With custom style

150

public String toJsonString() {

151

return ReflectionToStringBuilder.toString(this, ToStringStyle.JSON_STYLE);

152

}

153

154

// Exclude specific fields

155

public String toStringExcludePrice() {

156

return ReflectionToStringBuilder.toStringExclude(this, "price");

157

}

158

159

// Include only specific fields

160

public String toStringOnlyName() {

161

return ReflectionToStringBuilder.toStringInclude(this, "name");

162

}

163

}

164

```

165

166

### EqualsBuilder - Fluent equals() Construction

167

168

Creates robust equals() methods with null safety and type checking:

169

170

```java { .api }

171

import org.apache.commons.lang3.builder.EqualsBuilder;

172

```

173

174

#### Basic EqualsBuilder Usage

175

176

```java { .api }

177

public class Person {

178

private String firstName;

179

private String lastName;

180

private int age;

181

private Date birthDate;

182

private String[] hobbies;

183

184

@Override

185

public boolean equals(Object obj) {

186

if (this == obj) return true;

187

if (obj == null || getClass() != obj.getClass()) return false;

188

189

Person person = (Person) obj;

190

191

return new EqualsBuilder()

192

.append(firstName, person.firstName)

193

.append(lastName, person.lastName)

194

.append(age, person.age)

195

.append(birthDate, person.birthDate)

196

.append(hobbies, person.hobbies)

197

.isEquals();

198

}

199

}

200

```

201

202

#### EqualsBuilder Methods

203

204

```java { .api }

205

// Basic field comparison

206

public EqualsBuilder append(Object lhs, Object rhs)

207

public EqualsBuilder append(boolean lhs, boolean rhs)

208

public EqualsBuilder append(byte lhs, byte rhs)

209

public EqualsBuilder append(char lhs, char rhs)

210

public EqualsBuilder append(double lhs, double rhs)

211

public EqualsBuilder append(float lhs, float rhs)

212

public EqualsBuilder append(int lhs, int rhs)

213

public EqualsBuilder append(long lhs, long rhs)

214

public EqualsBuilder append(short lhs, short rhs)

215

216

// Array comparison

217

public EqualsBuilder append(Object[] lhs, Object[] rhs)

218

public EqualsBuilder append(boolean[] lhs, boolean[] rhs)

219

// ... similar for other primitive arrays

220

221

// Advanced comparison

222

public EqualsBuilder appendSuper(boolean superEquals)

223

public boolean isEquals()

224

```

225

226

#### Reflection-Based equals()

227

228

```java { .api }

229

public class Employee {

230

private String id;

231

private String name;

232

private String department;

233

private double salary;

234

235

@Override

236

public boolean equals(Object obj) {

237

return EqualsBuilder.reflectionEquals(this, obj);

238

}

239

240

// Exclude specific fields from comparison

241

public boolean equalsIgnoreSalary(Object obj) {

242

return EqualsBuilder.reflectionEquals(this, obj, "salary");

243

}

244

245

// Include only up to a certain class in hierarchy

246

public boolean equalsShallow(Object obj) {

247

return EqualsBuilder.reflectionEquals(this, obj, false, Employee.class);

248

}

249

}

250

```

251

252

### HashCodeBuilder - Fluent hashCode() Construction

253

254

Creates consistent hashCode() methods that work correctly with equals():

255

256

```java { .api }

257

import org.apache.commons.lang3.builder.HashCodeBuilder;

258

```

259

260

#### Basic HashCodeBuilder Usage

261

262

```java { .api }

263

public class Person {

264

private String firstName;

265

private String lastName;

266

private int age;

267

private Date birthDate;

268

269

@Override

270

public int hashCode() {

271

return new HashCodeBuilder(17, 37) // Two different odd prime numbers

272

.append(firstName)

273

.append(lastName)

274

.append(age)

275

.append(birthDate)

276

.toHashCode();

277

}

278

}

279

```

280

281

#### HashCodeBuilder Methods

282

283

```java { .api }

284

// Basic field hashing

285

public HashCodeBuilder append(Object object)

286

public HashCodeBuilder append(boolean value)

287

public HashCodeBuilder append(byte value)

288

public HashCodeBuilder append(char value)

289

public HashCodeBuilder append(double value)

290

public HashCodeBuilder append(float value)

291

public HashCodeBuilder append(int value)

292

public HashCodeBuilder append(long value)

293

public HashCodeBuilder append(short value)

294

295

// Array hashing

296

public HashCodeBuilder append(Object[] array)

297

public HashCodeBuilder append(boolean[] array)

298

// ... similar for other primitive arrays

299

300

// Advanced hashing

301

public HashCodeBuilder appendSuper(int superHashCode)

302

public int toHashCode()

303

```

304

305

#### Reflection-Based hashCode()

306

307

```java { .api }

308

public class Product {

309

private String sku;

310

private String name;

311

private double price;

312

private String category;

313

314

@Override

315

public int hashCode() {

316

return HashCodeBuilder.reflectionHashCode(this);

317

}

318

319

// Exclude specific fields

320

public int hashCodeIgnorePrice() {

321

return HashCodeBuilder.reflectionHashCode(this, "price");

322

}

323

324

// Custom initial values and multiplier

325

public int customHashCode() {

326

return HashCodeBuilder.reflectionHashCode(17, 37, this);

327

}

328

}

329

```

330

331

### CompareToBuilder - Fluent compareTo() Construction

332

333

Creates Comparable implementations with proper null handling:

334

335

```java { .api }

336

import org.apache.commons.lang3.builder.CompareToBuilder;

337

```

338

339

#### Basic CompareToBuilder Usage

340

341

```java { .api }

342

public class Person implements Comparable<Person> {

343

private String lastName;

344

private String firstName;

345

private int age;

346

private Date birthDate;

347

348

@Override

349

public int compareTo(Person other) {

350

return new CompareToBuilder()

351

.append(lastName, other.lastName)

352

.append(firstName, other.firstName)

353

.append(age, other.age)

354

.append(birthDate, other.birthDate)

355

.toComparison();

356

}

357

}

358

```

359

360

#### CompareToBuilder Methods

361

362

```java { .api }

363

// Basic field comparison

364

public CompareToBuilder append(Object lhs, Object rhs)

365

public CompareToBuilder append(Object lhs, Object rhs, Comparator<?> comparator)

366

public CompareToBuilder append(boolean lhs, boolean rhs)

367

public CompareToBuilder append(byte lhs, byte rhs)

368

public CompareToBuilder append(char lhs, char rhs)

369

public CompareToBuilder append(double lhs, double rhs)

370

public CompareToBuilder append(float lhs, float rhs)

371

public CompareToBuilder append(int lhs, int rhs)

372

public CompareToBuilder append(long lhs, long rhs)

373

public CompareToBuilder append(short lhs, short rhs)

374

375

// Array comparison

376

public CompareToBuilder append(Object[] lhs, Object[] rhs)

377

public CompareToBuilder append(Object[] lhs, Object[] rhs, Comparator<?> comparator)

378

// ... similar for other arrays

379

380

// Advanced comparison

381

public CompareToBuilder appendSuper(int superCompareTo)

382

public int toComparison()

383

```

384

385

#### Reflection-Based compareTo()

386

387

```java { .api }

388

public class Employee implements Comparable<Employee> {

389

private String department;

390

private String name;

391

private int level;

392

private double salary;

393

394

@Override

395

public int compareTo(Employee other) {

396

return CompareToBuilder.reflectionCompare(this, other);

397

}

398

399

// Exclude specific fields from comparison

400

public int compareIgnoreSalary(Employee other) {

401

return CompareToBuilder.reflectionCompare(this, other, "salary");

402

}

403

404

// Custom field order

405

public int compareCustomOrder(Employee other) {

406

return new CompareToBuilder()

407

.append(department, other.department) // Primary sort

408

.append(level, other.level) // Secondary sort

409

.append(name, other.name) // Tertiary sort

410

.toComparison();

411

}

412

}

413

```

414

415

## Advanced Builder Patterns

416

417

### Custom ToStringStyle

418

419

```java { .api }

420

public class CustomToStringStyle extends ToStringStyle {

421

422

public CustomToStringStyle() {

423

super();

424

this.setUseShortClassName(true);

425

this.setUseIdentityHashCode(false);

426

this.setFieldSeparator(" | ");

427

this.setFieldNameValueSeparator(": ");

428

this.setContentStart("[");

429

this.setContentEnd("]");

430

this.setNullText("NULL");

431

this.setArrayStart("{");

432

this.setArrayEnd("}");

433

this.setArraySeparator(", ");

434

}

435

}

436

437

// Usage

438

public String customToString() {

439

return new ToStringBuilder(this, new CustomToStringStyle())

440

.append("field1", value1)

441

.append("field2", value2)

442

.toString();

443

}

444

// Output: ClassName[field1: value1 | field2: value2]

445

```

446

447

### Builder Annotations

448

449

```java { .api }

450

import org.apache.commons.lang3.builder.ToStringExclude;

451

import org.apache.commons.lang3.builder.EqualsExclude;

452

import org.apache.commons.lang3.builder.HashCodeExclude;

453

454

public class User {

455

private String username;

456

private String email;

457

458

@ToStringExclude

459

@EqualsExclude

460

@HashCodeExclude

461

private String password; // Excluded from toString, equals, and hashCode

462

463

private Date lastLogin;

464

465

@Override

466

public String toString() {

467

return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);

468

// password field will be automatically excluded

469

}

470

471

@Override

472

public boolean equals(Object obj) {

473

return EqualsBuilder.reflectionEquals(this, obj);

474

// password field will be automatically excluded

475

}

476

477

@Override

478

public int hashCode() {

479

return HashCodeBuilder.reflectionHashCode(this);

480

// password field will be automatically excluded

481

}

482

}

483

```

484

485

### Complete Entity Example

486

487

```java { .api }

488

public class Order implements Comparable<Order> {

489

private Long id;

490

private String orderNumber;

491

private Date orderDate;

492

private BigDecimal totalAmount;

493

private OrderStatus status;

494

private Customer customer;

495

private List<OrderItem> items;

496

497

// Constructor, getters, setters...

498

499

@Override

500

public boolean equals(Object obj) {

501

if (this == obj) return true;

502

if (obj == null || getClass() != obj.getClass()) return false;

503

504

Order order = (Order) obj;

505

506

return new EqualsBuilder()

507

.append(id, order.id)

508

.append(orderNumber, order.orderNumber)

509

.isEquals();

510

}

511

512

@Override

513

public int hashCode() {

514

return new HashCodeBuilder(17, 37)

515

.append(id)

516

.append(orderNumber)

517

.toHashCode();

518

}

519

520

@Override

521

public String toString() {

522

return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)

523

.append("id", id)

524

.append("orderNumber", orderNumber)

525

.append("orderDate", orderDate)

526

.append("totalAmount", totalAmount)

527

.append("status", status)

528

.append("customerName", customer != null ? customer.getName() : null)

529

.append("itemCount", items != null ? items.size() : 0)

530

.toString();

531

}

532

533

@Override

534

public int compareTo(Order other) {

535

return new CompareToBuilder()

536

.append(orderDate, other.orderDate) // Primary: newest first

537

.append(id, other.id) // Secondary: by ID

538

.toComparison();

539

}

540

541

// Debug toString with all details

542

public String toDetailedString() {

543

return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)

544

.append("id", id)

545

.append("orderNumber", orderNumber)

546

.append("orderDate", orderDate)

547

.append("totalAmount", totalAmount)

548

.append("status", status)

549

.append("customer", customer)

550

.append("items", items)

551

.toString();

552

}

553

}

554

```

555

556

## Builder Utilities Integration

557

558

### Factory Methods for Builders

559

560

```java { .api }

561

public final class BuilderUtils {

562

563

// Fluent builder creation

564

public static ToStringBuilder toStringBuilder(Object object) {

565

return new ToStringBuilder(object, ToStringStyle.SHORT_PREFIX_STYLE);

566

}

567

568

public static ToStringBuilder jsonBuilder(Object object) {

569

return new ToStringBuilder(object, ToStringStyle.JSON_STYLE);

570

}

571

572

public static EqualsBuilder equalsBuilder() {

573

return new EqualsBuilder();

574

}

575

576

public static HashCodeBuilder hashCodeBuilder() {

577

return new HashCodeBuilder(17, 37);

578

}

579

580

public static CompareToBuilder compareToBuilder() {

581

return new CompareToBuilder();

582

}

583

584

// Null-safe reflection methods

585

public static String safeToString(Object obj) {

586

return obj != null ? ReflectionToStringBuilder.toString(obj) : "null";

587

}

588

589

public static boolean safeEquals(Object obj1, Object obj2) {

590

if (obj1 == obj2) return true;

591

if (obj1 == null || obj2 == null) return false;

592

if (obj1.getClass() != obj2.getClass()) return false;

593

594

return EqualsBuilder.reflectionEquals(obj1, obj2);

595

}

596

597

public static int safeHashCode(Object obj) {

598

return obj != null ? HashCodeBuilder.reflectionHashCode(obj) : 0;

599

}

600

}

601

```

602

603

### Validation with Builders

604

605

```java { .api }

606

@Component

607

public class EntityValidator {

608

609

public <T> void validateEqualsHashCode(T obj1, T obj2) {

610

boolean equals = obj1.equals(obj2);

611

boolean hashCodesEqual = obj1.hashCode() == obj2.hashCode();

612

613

if (equals && !hashCodesEqual) {

614

throw new IllegalStateException(

615

"Objects are equal but have different hash codes: " +

616

"obj1.hashCode()=" + obj1.hashCode() +

617

", obj2.hashCode()=" + obj2.hashCode());

618

}

619

620

// Log for debugging

621

log.debug("Validation passed for objects: {}, {}",

622

safeToString(obj1), safeToString(obj2));

623

}

624

625

public <T extends Comparable<T>> void validateComparable(T obj1, T obj2) {

626

int comparison = obj1.compareTo(obj2);

627

boolean equals = obj1.equals(obj2);

628

629

if (comparison == 0 && !equals) {

630

throw new IllegalStateException(

631

"Objects compare as equal but are not equal: " +

632

safeToString(obj1) + " vs " + safeToString(obj2));

633

}

634

635

if (comparison != 0 && equals) {

636

throw new IllegalStateException(

637

"Objects are equal but don't compare as equal: " +

638

safeToString(obj1) + " vs " + safeToString(obj2));

639

}

640

}

641

}

642

```

643

644

### Performance Considerations

645

646

```java { .api }

647

public class OptimizedEntity {

648

private final String id;

649

private final String name;

650

private final int value;

651

652

// Cache hash code for immutable objects

653

private transient int hashCode = 0;

654

655

public OptimizedEntity(String id, String name, int value) {

656

this.id = id;

657

this.name = name;

658

this.value = value;

659

}

660

661

@Override

662

public boolean equals(Object obj) {

663

// Fast path for same reference

664

if (this == obj) return true;

665

if (obj == null || getClass() != obj.getClass()) return false;

666

667

OptimizedEntity other = (OptimizedEntity) obj;

668

669

// Most discriminating field first

670

return new EqualsBuilder()

671

.append(id, other.id) // Usually unique

672

.append(value, other.value) // Numeric comparison is fast

673

.append(name, other.name) // String comparison last

674

.isEquals();

675

}

676

677

@Override

678

public int hashCode() {

679

// Cache hash code for immutable objects

680

if (hashCode == 0) {

681

hashCode = new HashCodeBuilder(17, 37)

682

.append(id)

683

.append(name)

684

.append(value)

685

.toHashCode();

686

}

687

return hashCode;

688

}

689

690

@Override

691

public String toString() {

692

// Use simple concatenation for performance-critical paths

693

return getClass().getSimpleName() + "[id=" + id + ",name=" + name + ",value=" + value + "]";

694

}

695

}

696

```

697

698

The builder utilities in Apache Commons Lang provide a robust foundation for implementing the essential Object methods with proper null safety, array handling, and customizable formatting, reducing boilerplate code while ensuring correctness and consistency.