For the complete documentation index, see llms.txt. This page is also available as Markdown.

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:

  • DEFAULTHashSet, fastest, no ordering

  • LINKEDLinkedHashSet, preserves insertion order

  • SORTEDTreeSet, natural ordering via Compare.invoke

// Create a Set via function
s = setNew()

// Create a Set via literal syntax
s = set{ 1, 2, 3 }

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:

Type
Alias
Java Backing
Ordering

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

Function
Purpose
Example

setNew()

Create new Set

setNew( type="linked" )

setOf()

Create from varargs

setOf( 1, 2, 3 )

➕ Mutation Functions

Function
Purpose
Example

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

Function
Purpose
Example

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

Function
Purpose
Example

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

Function
Purpose
Example

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

Function
Purpose
Example

boxSetSize()

Get element count

boxSetSize( set )5

🔄 Conversion Functions

Function
Purpose
Example

boxSetToArray()

Convert to Array

boxSetToArray( set )[1, 2, 3]

boxSetToList()

Convert to list string

boxSetToList( set, "-" )"1-2-3"

⚙️ 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

BoxLang's === operator normalizes values along the language's type system before comparing:

Type Family
Includes
Comparison Rule

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()?

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:

ArraysStructuresRangesQueries

Last updated

Was this helpful?