Sets
A collection of unique elements with algebra operations
BoxLang 1.14.0 introduces BoxSet as a brand-new first-class type, wrapping java.util.Set with full BoxLang integration including member-function dispatch, change listeners, metadata, and JSON serialization. Sets provide a powerful collection model for working with unique values, making them ideal for deduplication, membership testing, tagging systems, permissions, caching, filtering, mathematics, and data comparison workflows.
Unlike arrays, sets enforce uniqueness by design and offer highly efficient lookup operations. BoxLang elevates sets to a first-class citizen with literal syntax, functional collection operations, and rich operator overloads for set algebra—including unions, intersections, differences, and symmetric differences—making complex data manipulation both expressive and concise.
Whether you're comparing datasets, managing unique identifiers, processing large collections, implementing access-control rules, or building recommendation and analytics engines, BoxSet provides a performant and elegant foundation for working with distinct values at scale.
Sets support three backing variants:
DEFAULT—HashSet, fastest, no orderingLINKED—LinkedHashSet, preserves insertion orderSORTED—TreeSet, natural ordering viaCompare.invoke
// Create a Set via function
s = setNew()
// Create a Set via literal syntax
s = set{ 1, 2, 3 }Tip Underneath the hood, all BoxLang Sets are based on the java.util.Set interface. So if you come from a Java background, Sets are untyped HashSet, LinkedHashSet, or TreeSet wrappers.
Java Set Interoperability: Any Java Set implementation can be used with BoxLang set functions! BoxLang set BIFs and member functions work seamlessly with Java Sets.
📥 Creating Sets
BoxLang provides multiple ways to create Sets:
setNew()
Creates a new Set with optional type, values, and case-sensitivity settings.
setOf( ...values )
Creates a Set from positional varargs. Duplicates are automatically removed.
Literal Syntax: set{ ... }
BoxLang supports a literal syntax for Sets using the set keyword followed by braces.
The set token is matched as an identifier and the rule is parser-gated so it does not collide with variables named set. You can still use set as a variable name.
From an Array
Convert an Array to a Set using the .toSet() member method.
From a String
Split a list-delimited string into a Set using .listToSet().
From a Query
Convert a Query to a Set of row structs.
🔧 Set Types
BoxLang supports three Set variants:
default
hash
HashSet
No ordering (fastest)
linked
ordered
LinkedHashSet
Preserves insertion order
sorted
tree
TreeSet
Natural ascending order
🔑 Accessing Set Elements
Sets are unordered (except linked/sorted variants), so you don't access elements by index. Instead, you test membership or iterate.
contains( value ) / has( value )
Test whether a value exists in the Set.
Iteration
📚 Set Built-In Functions
BoxLang provides a comprehensive set of Set BIFs organized by functionality. All Set BIFs can be called as member methods on Set objects.
🔨 Creation Functions
setNew()
Create new Set
setNew( type="linked" )
setOf()
Create from varargs
setOf( 1, 2, 3 )
➕ Mutation Functions
boxSetAdd()
Add element
boxSetAdd( set, value )
boxSetAddAll()
Add multiple elements
boxSetAddAll( set, collection )
boxSetRemove()
Remove element
boxSetRemove( set, value )
boxSetRemoveAll()
Remove multiple elements
boxSetRemoveAll( set, collection )
boxSetRetainAll()
Keep only specified elements
boxSetRetainAll( set, collection )
boxSetClear()
Remove all elements
boxSetClear( set )
🔍 Query Functions
boxSetContains()
Test membership
boxSetContains( set, value ) → true
boxSetContainsAll()
Test all members
boxSetContainsAll( set, collection ) → true
boxSetIsEmpty()
Check if empty
boxSetIsEmpty( set ) → false
boxSetEquals()
Compare Sets
boxSetEquals( set1, set2 ) → true
boxSetIsSubsetOf()
Test subset
boxSetIsSubsetOf( a, b ) → true
boxSetIsSupersetOf()
Test superset
boxSetIsSupersetOf( a, b ) → true
boxSetIsDisjointFrom()
Test no overlap
boxSetIsDisjointFrom( a, b ) → true
🔀 Algebra Functions
boxSetUnion()
Combine all elements
boxSetUnion( a, b )
boxSetIntersection()
Common elements
boxSetIntersection( a, b )
boxSetDifference()
Elements in A not in B
boxSetDifference( a, b )
boxSetSymmetricDifference()
Elements in either, not both
boxSetSymmetricDifference( a, b )
🔄 Functional Functions
boxSetEach()
Iterate each element
boxSetEach( set, callback )
boxSetMap()
Transform elements
boxSetMap( set, callback )
boxSetFilter()
Filter elements
boxSetFilter( set, callback )
boxSetReject()
Reject elements
boxSetReject( set, callback )
boxSetReduce()
Reduce to single value
boxSetReduce( set, callback, init )
boxSetEvery()
Test all elements
boxSetEvery( set, callback ) → true
boxSetSome()
Test any element
boxSetSome( set, callback ) → true
boxSetNone()
Test no elements match
boxSetNone( set, callback ) → true
boxSetFind()
Find first match
boxSetFind( set, callback )
📏 Information Functions
boxSetSize()
Get element count
boxSetSize( set ) → 5
🔄 Conversion Functions
boxSetToArray()
Convert to Array
boxSetToArray( set ) → [1, 2, 3]
boxSetToList()
Convert to list string
boxSetToList( set, "-" ) → "1-2-3"
Complete Reference: For detailed documentation of each function, visit the Set BIF Reference.
⚙️ Member Functions
All Set BIFs can be called as member functions on Set objects for cleaner, more fluent code:
🔀 Set Algebra
Sets support four fundamental algebra operations:
Union
Combines all unique elements from both Sets.
Intersection
Returns elements common to both Sets.
Difference
Returns elements in the first Set that are not in the second.
Symmetric Difference
Returns elements in either Set but not in both.
🔣 Operators
Set algebra is also available via overloaded operators:
The right-hand operand is accepted "loose" (Array, list-delimited string, Range, etc.) when either operand is a Set.
When neither operand is a Set, these operators fall through to standard math: 2 + 3 = 5, 5 - 2 = 3, 4 * 3 = 12, 2 ^ 3 = 8.
Compound operators are also supported:
🔄 Functional Programming
Sets support a full functional programming pipeline:
🔄 Conversion
Set to Array
Set to List
Array to Set
See Arrays for the .toSet() member method.
🔤 Case Sensitivity
By default, Sets are case-insensitive for string elements. Different cases of the same string are treated as duplicates.
To treat different cases as distinct elements, pass caseSensitive=true:
Numeric normalization: Case sensitivity does not affect numeric normalization. 1, 1L, and 1.0 are always treated as the same numeric value regardless of case sensitivity setting.
⚖️ Equality and Uniqueness
BoxLang Sets determine membership using the === (strict equality / identity) operator, not Java's equals() method. This ensures Set behavior is consistent with BoxLang's type system and loose typing conventions, unlike Adobe CF which delegates directly to java.util.Set.equals().
How === Determines Set Membership
=== Determines Set MembershipBoxLang's === operator normalizes values along the language's type system before comparing:
String
java.lang.String, java.lang.Character, char[]
Case-insensitive comparison
Numeric
Integer, Short, Long, Double, Float, BigInteger, BigDecimal
Compared by numeric value
DateTime
DateTime, ZonedDateTime, Calendar, LocalDateTime, LocalDate
Compared by epoch millis
Array
BoxLang Array, java.util.List
Falls back to Java's equals()
Struct
BoxLang Struct, java.util.Map
Falls back to Java's equals()
All Others
Same class + Comparable
Uses compareTo()
All Others
Same class, not Comparable
Falls back to Java's equals()
Practical Implications
This approach follows the same precedent as JavaScript, Ruby, and PHP — using a strict-type-aware equality check for Set membership, rather than Java's type-sensitive equals().
Why Not Java's equals()?
equals()?If you delegate uniqueness to Java's HashSet.equals(), which considers Java type and hashCode, this will lead to counter-intuitive behavior:
BoxLang Sets are case-insensitive by default, matching BoxLang's case-insensitive string comparison semantics. See Case Sensitivity for opt-in case-sensitive behavior.
Java Set Wrapping: If you pass a native Java Set to a BoxLang Set BIF or call member methods on a Java Set instance, BoxLang respects the Java class's own equality and case-sensitivity behavior.
🔧 Java Interop
A java.util.Set passed to a Set-typed BIF argument is wrapped (not copied) so that mutations propagate back to the underlying Java object — same contract as Array wrapping a Java List.
struct.keySet() and struct.valueSet()
Structs provide methods to extract keys or values as Sets:
The keySet inherits case-sensitivity from the parent struct.
📦 JSON Serialization
Sets serialize to JSON arrays:
🛡️ Unmodifiable Sets
Sets can be made immutable:
Tip: Check out all the Set BIF reference and member functions for more capabilities.
🔗 Related Documentation
ArraysStructuresRangesQueriesLast updated
Was this helpful?
