Lang Package
The org.apache.juneau.commons.lang package provides language utilities including value wrappers, version management, string formatting, state enums, and other common language constructs.
Key Classes
Holder
A generic mutable value wrapper.
// Basic usage
Holder<String> name = Holder.of("John");
name.set("Jane");
String result = name.get(); // Returns "Jane"
// Use in lambda (effectively final variable)
Holder<String> result = Holder.empty();
list.forEach(x -> {
if (x.matches(criteria)) {
result.set(x);
}
});
// With default values
Holder<String> optional = Holder.empty();
String value = optional.orElse("default"); // Returns "default"
// Mapping values
Holder<Integer> number = Holder.of(5);
Holder<String> text = number.map(Object::toString); // Holder of "5"
// With listener for change notification
Holder<String> monitored = Holder.of("initial")
.listener(newValue -> log("Value changed to: " + newValue));
monitored.set("updated"); // Triggers listener
Specialized Holder Classes
IntegerHolder
Mutable integer with additional convenience methods.
IntegerHolder counter = IntegerHolder.of(0);
counter.increment(); // 1
counter.decrement(); // 0
int value = counter.getAndIncrement(); // Returns 0, then sets to 1
LongHolder
Mutable long with additional convenience methods.
LongHolder counter = LongHolder.of(0L);
counter.increment(); // 1L
counter.decrement(); // 0L
long value = counter.getAndIncrement(); // Returns 0L, then sets to 1L
ByteHolder
Mutable byte with additional convenience methods.
ByteHolder counter = ByteHolder.create(); // Initialized to 0
counter.increment(); // 1
counter.decrement(); // 0
byte value = counter.incrementAndGet(); // Returns 1
ShortHolder
Mutable short with additional convenience methods.
ShortHolder counter = ShortHolder.create(); // Initialized to 0
counter.increment(); // 1
short value = counter.getAndIncrement(); // Returns 1, then sets to 2
CharHolder
Mutable character with convenience methods for incrementing/decrementing and matching against a set of characters.
CharHolder ch = CharHolder.of('A');
ch.increment(); // 'B'
boolean found = ch.isAny("XYZB"); // true - matches a character in the string
DoubleHolder and FloatHolder
Mutable double/float with precision-based equality checks, since exact == comparisons on floating-point values are unreliable.
DoubleHolder pi = DoubleHolder.of(3.14159);
boolean close = pi.is(3.14, 0.01); // true - within 0.01
boolean anyClose = pi.isAny(0.01, 1.0, 3.15, 5.0); // true - matches 3.15 within 0.01
BooleanHolder
Nullable boolean with convenience methods.
BooleanHolder flag = BooleanHolder.of(true);
flag.isTrue(); // true
flag.isNotTrue(); // false
BooleanHolder nullable = BooleanHolder.empty();
nullable.isTrue(); // false (null is not true)
nullable.isNotTrue(); // true (null is not true)
Flag
Non-nullable boolean flag (true/false only, no null state).
Flag flag = Flag.of(true);
flag.isTrue(); // true
flag.isFalse(); // false
flag.toggle(); // Switches to false
StringHolder
Mutable string with convenience methods for equality testing.
StringHolder name = StringHolder.of("John");
// Check equality
if (name.is("John")) {
System.out.println("Name is John");
}
// Check multiple values
if (name.isAny("John", "Jane", "Bob")) {
System.out.println("Name found");
}
WeightedAverage
Accumulates a running weighted average of numbers, re-weighting on each call to add(int, Number).
WeightedAverage avg = new WeightedAverage();
avg.add(2, 10.0); // weight 2, value 10.0
avg.add(1, 40.0); // weight 1, value 40.0
double result = avg.getValue(); // (10.0*2 + 40.0*1) / 3 = 20.0
StringFormat
Cacheable printf-style string formatter (backed by String.format semantics).
// Printf-style formatting
StringFormat fmt = StringFormat.ofPrintf("Hello %s, you have %d items");
String result = fmt.format("John", 5);
// Returns: "Hello John, you have 5 items"
// Printf with explicit argument indices
StringFormat fmt2 = StringFormat.ofPrintf("%1$s loves %2$s, and %1$s also loves %3$s");
String result2 = fmt2.format("Alice", "Bob", "Charlie");
// Returns: "Alice loves Bob, and Alice also loves Charlie"
// A one-shot helper is also available for non-cached use
String result3 = StringFormat.formatPrintf("%s has %d items", "Alice", 10);
// Returns: "Alice has 10 items"
StringFormat is printf-only — MessageFormat-style {0} placeholders are not recognized and render
literally ({ and ' are treated as ordinary text). This applies consistently across the terse helpers too:
Shorts.f() / Shorts.fs() and StringUtils.format(...) are also printf-only. If you need MessageFormat-style
{0} / ''-quoting, use Shorts.mf() / Shorts.mfs() / StringUtils.mformat(...) (backed directly by
java.text.MessageFormat) instead — there is no single class that mixes both grammars in one pattern. See the
10.0.0 release notes for migration details.
Which String-Formatting Entry Point Should I Use?
StringFormat, StringUtils.format(...)/mformat(...), and Shorts.f()/mf() all coexist deliberately —
they're three different call-site shapes over the same two underlying grammars (printf and MessageFormat),
not three competing implementations. Use this table to pick the right one:
| Use... | When... |
|---|---|
Shorts.f(pattern, args) / Shorts.mf(pattern, args) | You want the terse, one-off, static-import-friendly call — most call sites (logging, exception messages, assertions). f = printf-style, mf = MessageFormat-style. |
Shorts.fs(pattern, args) / Shorts.mfs(pattern, args) | Same as above, but the formatting cost should be deferred — e.g. a logging API that takes a Supplier<String> and only calls it when the log level is enabled. |
StringUtils.format(pattern, args) / mformat(pattern, args) | You're already in juneau-commons code that avoids the Shorts static-import convention, or you want the fully-qualified name for clarity in a public API signature. Shorts.f/mf are thin aliases over these two methods — behavior is identical either way. |
StringFormat.ofPrintf(pattern) | The same pattern is reused repeatedly (e.g. in a loop, or as a static final field) and you want to pay the pattern-parsing cost once via the built-in cache, rather than re-parsing on every call. Printf-style only — there is no StringFormat MessageFormat counterpart. |
StringFormat is the odd one out shape-wise (a stateful/cacheable class, not a static one-shot method) — reach
for it only when reuse/caching matters. For everything else, Shorts.f/mf/fs/mfs are the recommended
entry point; StringUtils.format/mformat are the methods they delegate to and remain public for callers
that prefer explicit, non-abbreviated names.
HashCode
Utility class for generating integer hash codes.
int hashCode = HashCode.create()
.add("foobar")
.add(myObject)
.add(123)
.get();
Version
Version management utility.
Version version = Version.of("1.2.3");
version.getMajor(); // Optional.of(1)
version.getMinor(); // Optional.of(2)
version.getMaintenance(); // Optional.of(3)
int major = version.getMajor().orElse(0); // 1
// Compare versions
Version v1 = Version.of("1.2.3");
Version v2 = Version.of("1.2.4");
int comparison = v1.compareTo(v2); // -1 (v1 < v2)
VersionRange
Version range utility for checking if a version string falls within an OSGi-style range.
VersionRange range = VersionRange.of("[1.0.0,2.0.0)");
boolean inRange = range.matches("1.5.0"); // true
StateEnum
Enumeration of state machine states for use in parsing operations.
import static org.apache.juneau.commons.lang.StateEnum.*;
// Use in state machine
var state = S1;
if (state == S1) {
// Handle state S1
} else if (state == S2) {
// Handle state S2
}
TriState
Three-state enum (TRUE, FALSE, UNKNOWN).
TriState state = TriState.TRUE;
state.isTrue(); // true
state.isFalse(); // false
state.isUnknown(); // false
TriState unknown = TriState.UNKNOWN;
unknown.isTrue(); // false
unknown.isFalse(); // false
unknown.isUnknown(); // true
AsciiSet and AsciiMap
Utilities for working with ASCII character sets and maps.
AsciiSet asciiSet = AsciiSet.of("abc");
boolean contains = asciiSet.contains('a'); // true
AsciiMap<String> asciiMap = AsciiMap.of();
asciiMap.put('a', "alpha");
String value = asciiMap.get('a'); // "alpha"
Common Patterns
Mutable Values in Lambdas
// Use Holder to create effectively final mutable variables
Holder<String> result = Holder.empty();
list.stream()
.filter(x -> x.matches(pattern))
.forEach(x -> result.set(x));
String found = result.orElse("not found");
Version Checking
String current = "1.2.3";
VersionRange supported = VersionRange.of("[1.0.0,2.0.0)");
if (supported.matches(current)) {
// Version is supported
}
State Machine
import static org.apache.juneau.commons.lang.StateEnum.*;
StateEnum state = S1;
while (state != null) {
switch (state) {
case S1:
// Process S1
state = S2;
break;
case S2:
// Process S2
state = S3;
break;
// ...
}
}