A Kotlin set is a generic collection interface that stores unique elements without allowing duplicates. The Kotlin set collection provides two main categories: immutable sets created with setOf() and mutable sets created with mutableSetOf(). Every Kotlin set implementation automatically handles duplicate removal, making it perfect for scenarios where data uniqueness is essential.
The Kotlin set interface extends the Collection interface and provides specialized operations for set-specific functionality like union, intersection, and difference operations.
The setOf() function creates a read-only Kotlin set that supports only read operations. This Kotlin set implementation returns a LinkedHashSet typed as Set interface, preserving insertion order while preventing modifications.
// Creating immutable Kotlin set
val colors = setOf("Red", "Green", "Blue")
val numbers = setOf(1, 2, 3, 4, 5)
val mixedSet = setOf("Hello", 42, true)
Key Properties of setOf():
The mutableSetOf() function creates a Kotlin set that supports both read and write operations. This Kotlin set implementation returns a LinkedHashSet that allows modifications while maintaining insertion order.
// Creating mutable Kotlin set
val mutableColors = mutableSetOf("Red", "Green", "Blue")
mutableColors.add("Yellow")
mutableColors.remove("Red")
Key Properties of mutableSetOf():
The hashSetOf() function creates a Kotlin set using HashSet implementation, providing fastest performance for basic operations but without guaranteed iteration order.
// Creating HashSet-based Kotlin set
val hashNumbers = hashSetOf(10, 20, 30, 40)
hashNumbers.add(50)
println(hashNumbers) // Order may vary: [20, 40, 10, 50, 30]
Key Properties of hashSetOf():
The linkedSetOf() function creates a Kotlin set that combines HashSet performance with insertion order maintenance.
// Creating LinkedHashSet-based Kotlin set
val linkedColors = linkedSetOf("Purple", "Orange", "Pink")
linkedColors.add("Cyan")
println(linkedColors) // [Purple, Orange, Pink, Cyan]
Key Properties of linkedSetOf():
The sortedSetOf() function creates a Kotlin set that automatically sorts elements using natural ordering or custom comparator.
// Creating sorted Kotlin set
val sortedNumbers = sortedSetOf(5, 1, 9, 3, 7)
println(sortedNumbers) // [1, 3, 5, 7, 9]
val sortedStrings = sortedSetOf("Zebra", "Apple", "Banana")
println(sortedStrings) // [Apple, Banana, Zebra]
Key Properties of sortedSetOf():
Every Kotlin set provides essential methods for element management and querying:
val programmingLanguages = mutableSetOf("Kotlin", "Java", "Python")
// Check if element exists
val hasKotlin = programmingLanguages.contains("Kotlin") // true
val hasSwift = "Swift" in programmingLanguages // false
// Get set size
val size = programmingLanguages.size // 3
// Check if empty
val isEmpty = programmingLanguages.isEmpty() // false
// Add elements
programmingLanguages.add("JavaScript")
programmingLanguages.addAll(listOf("Go", "Rust"))
// Remove elements
programmingLanguages.remove("Python")
programmingLanguages.removeAll(listOf("Go", "Rust"))
Kotlin set collections support mathematical set operations for combining and comparing sets:
val frontend = setOf("JavaScript", "TypeScript", "Vue")
val backend = setOf("Kotlin", "Java", "Python")
// Union combines all unique elements
val fullStack = frontend union backend
println(fullStack) // [JavaScript, TypeScript, Vue, Kotlin, Java, Python]
val kotlinSkills = setOf("Android", "Backend", "Multiplatform")
val javaSkills = setOf("Backend", "Enterprise", "Android")
// Intersection finds common elements
val commonSkills = kotlinSkills intersect javaSkills
println(commonSkills) // [Android, Backend]
val allFrameworks = setOf("Spring", "Ktor", "Micronaut", "Quarkus")
val javaFrameworks = setOf("Spring", "Micronaut", "Quarkus")
// Difference finds elements in first set but not in second
val kotlinFrameworks = allFrameworks subtract javaFrameworks
println(kotlinFrameworks) // [Ktor]
val androidLibs = setOf("Jetpack", "Compose", "Room")
val iosLibs = setOf("SwiftUI", "CoreData", "Combine")
// Symmetric difference: elements in either set but not both
val platformSpecific = (androidLibs - iosLibs) union (iosLibs - androidLibs)
println(platformSpecific) // [Jetpack, Compose, Room, SwiftUI, CoreData, Combine]
Kotlin set collections support functional programming operations for data transformation:
val numbers = setOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// Filter elements
val evenNumbers = numbers.filter { it % 2 == 0 }.toSet()
println(evenNumbers) // [2, 4, 6, 8, 10]
// Transform elements
val squaredNumbers = numbers.map { it * it }.toSet()
println(squaredNumbers) // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
// Find elements
val firstEven = numbers.first { it % 2 == 0 } // 2
val lastOdd = numbers.last { it % 2 == 1 } // 9
// Aggregate operations
val sum = numbers.sum() // 55
val max = numbers.maxOrNull() // 10
val min = numbers.minOrNull() // 1
Kotlin set implementations can be converted between mutable and immutable versions:
// Convert mutable to immutable
val mutableDevices = mutableSetOf("Android", "iOS", "Web")
val immutableDevices: Set<String> = mutableDevices.toSet()
// Convert immutable to mutable
val readOnlyColors = setOf("Red", "Green", "Blue")
val mutableColors: MutableSet<String> = readOnlyColors.toMutableSet()
// Convert to specific implementations
val hashSet: HashSet<String> = readOnlyColors.toCollection(HashSet())
val linkedHashSet: LinkedHashSet<String> = readOnlyColors.toCollection(LinkedHashSet())
Understanding Kotlin set performance helps choose the right implementation:
Kotlin Set Type | Add/Remove | Contains | Iteration | Memory | Order |
---|---|---|---|---|---|
HashSet | O(1) | O(1) | O(n) | Low | None |
LinkedHashSet | O(1) | O(1) | O(n) | Medium | Insertion |
TreeSet | O(log n) | O(log n) | O(n) | Medium | Sorted |
data class User(val id: String, val name: String)
data class Permission(val name: String, val level: Int)
class PermissionManager {
private val userPermissions = mutableMapOf<User, MutableSet<Permission>>()
fun grantPermission(user: User, permission: Permission) {
userPermissions.getOrPut(user) { mutableSetOf() }.add(permission)
}
fun revokePermission(user: User, permission: Permission) {
userPermissions[user]?.remove(permission)
}
fun hasPermission(user: User, permission: Permission): Boolean {
return userPermissions[user]?.contains(permission) ?: false
}
fun getCommonPermissions(user1: User, user2: User): Set<Permission> {
val permissions1 = userPermissions[user1] ?: emptySet()
val permissions2 = userPermissions[user2] ?: emptySet()
return permissions1 intersect permissions2
}
}
data class Article(val id: String, val title: String, val tags: MutableSet<String>)
class ArticleManager {
private val articles = mutableListOf<Article>()
fun addArticle(article: Article) {
articles.add(article)
}
fun findArticlesByTag(tag: String): List<Article> {
return articles.filter { tag in it.tags }
}
fun findArticlesByAnyTag(tags: Set<String>): List<Article> {
return articles.filter { article ->
(article.tags intersect tags).isNotEmpty()
}
}
fun findArticlesByAllTags(tags: Set<String>): List<Article> {
return articles.filter { article ->
tags.all { tag -> tag in article.tags }
}
}
fun getAllTags(): Set<String> {
return articles.flatMap { it.tags }.toSet()
}
fun getPopularTags(minCount: Int): Set<String> {
val tagCounts = mutableMapOf<String, Int>()
articles.forEach { article ->
article.tags.forEach { tag ->
tagCounts[tag] = tagCounts.getOrDefault(tag, 0) + 1
}
}
return tagCounts.filterValues { it >= minCount }.keys.toSet()
}
}
data class Dependency(val name: String, val version: String)
class DependencyResolver {
private val projectDependencies = mutableSetOf<Dependency>()
private val optionalDependencies = mutableSetOf<Dependency>()
fun addDependency(dependency: Dependency, optional: Boolean = false) {
if (optional) {
optionalDependencies.add(dependency)
} else {
projectDependencies.add(dependency)
}
}
fun getAllDependencies(): Set<Dependency> {
return projectDependencies union optionalDependencies
}
fun getRequiredDependencies(): Set<Dependency> {
return projectDependencies.toSet()
}
fun getOptionalDependencies(): Set<Dependency> {
return optionalDependencies.toSet()
}
fun resolveDependencies(): Set<Dependency> {
val resolved = mutableSetOf<Dependency>()
// Add all required dependencies
resolved.addAll(projectDependencies)
// Add optional dependencies that don't conflict
optionalDependencies.forEach { optional ->
val conflicts = resolved.any { existing ->
existing.name == optional.name && existing.version != optional.version
}
if (!conflicts) {
resolved.add(optional)
}
}
return resolved
}
}
Here’s a comprehensive example demonstrating all Kotlin set concepts with imports and expected output:
import kotlin.random.Random
fun main() {
println("=== Kotlin Set Comprehensive Example ===\n")
// 1. Creating different types of sets
println("1. Creating Different Set Types:")
val immutableColors = setOf("Red", "Green", "Blue", "Red") // Duplicate ignored
val mutableNumbers = mutableSetOf(1, 2, 3)
val hashSet = hashSetOf("Apple", "Banana", "Cherry")
val linkedSet = linkedSetOf("First", "Second", "Third")
val sortedSet = sortedSetOf(5, 1, 9, 3, 7)
println("Immutable Set: $immutableColors")
println("Mutable Set: $mutableNumbers")
println("Hash Set: $hashSet")
println("Linked Set: $linkedSet")
println("Sorted Set: $sortedSet\n")
// 2. Set operations
println("2. Set Operations:")
mutableNumbers.add(4)
mutableNumbers.addAll(listOf(5, 6, 7))
println("After adding elements: $mutableNumbers")
mutableNumbers.remove(1)
mutableNumbers.removeAll(listOf(6, 7))
println("After removing elements: $mutableNumbers")
println("Contains 3: ${mutableNumbers.contains(3)}")
println("Contains 10: ${10 in mutableNumbers}")
println("Set size: ${mutableNumbers.size}")
println("Is empty: ${mutableNumbers.isEmpty()}\n")
// 3. Mathematical set operations
println("3. Mathematical Set Operations:")
val frontend = setOf("HTML", "CSS", "JavaScript", "React")
val backend = setOf("Kotlin", "Java", "Python", "JavaScript")
val union = frontend union backend
val intersection = frontend intersect backend
val difference = frontend subtract backend
val symmetricDiff = (frontend - backend) union (backend - frontend)
println("Frontend: $frontend")
println("Backend: $backend")
println("Union: $union")
println("Intersection: $intersection")
println("Frontend - Backend: $difference")
println("Symmetric Difference: $symmetricDiff\n")
// 4. Functional operations
println("4. Functional Operations:")
val numbers = setOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenNumbers = numbers.filter { it % 2 == 0 }.toSet()
val squaredNumbers = numbers.map { it * it }.toSet()
val numbersAboveFive = numbers.filter { it > 5 }.toSet()
println("Original: $numbers")
println("Even numbers: $evenNumbers")
println("Squared numbers: $squaredNumbers")
println("Numbers > 5: $numbersAboveFive")
val sum = numbers.sum()
val max = numbers.maxOrNull()
val min = numbers.minOrNull()
val average = numbers.average()
println("Sum: $sum, Max: $max, Min: $min, Average: $average\n")
// 5. Real-world example: Student Course Management
println("5. Student Course Management System:")
data class Student(val id: String, val name: String)
data class Course(val code: String, val name: String)
class CourseManager {
private val studentCourses = mutableMapOf<Student, MutableSet<Course>>()
fun enrollStudent(student: Student, course: Course) {
studentCourses.getOrPut(student) { mutableSetOf() }.add(course)
}
fun getStudentCourses(student: Student): Set<Course> {
return studentCourses[student]?.toSet() ?: emptySet()
}
fun getCommonCourses(student1: Student, student2: Student): Set<Course> {
val courses1 = studentCourses[student1] ?: emptySet()
val courses2 = studentCourses[student2] ?: emptySet()
return courses1 intersect courses2
}
fun getAllCourses(): Set<Course> {
return studentCourses.values.flatten().toSet()
}
fun getStudentsInCourse(course: Course): Set<Student> {
return studentCourses.filterValues { courses -> course in courses }.keys.toSet()
}
}
val courseManager = CourseManager()
val alice = Student("1", "Alice")
val bob = Student("2", "Bob")
val charlie = Student("3", "Charlie")
val kotlin = Course("CS101", "Kotlin Programming")
val android = Course("CS102", "Android Development")
val algorithms = Course("CS201", "Data Structures & Algorithms")
val databases = Course("CS301", "Database Systems")
// Enroll students
courseManager.enrollStudent(alice, kotlin)
courseManager.enrollStudent(alice, android)
courseManager.enrollStudent(alice, algorithms)
courseManager.enrollStudent(bob, kotlin)
courseManager.enrollStudent(bob, algorithms)
courseManager.enrollStudent(bob, databases)
courseManager.enrollStudent(charlie, android)
courseManager.enrollStudent(charlie, databases)
println("Alice's courses: ${courseManager.getStudentCourses(alice).map { it.name }}")
println("Bob's courses: ${courseManager.getStudentCourses(bob).map { it.name }}")
println("Charlie's courses: ${courseManager.getStudentCourses(charlie).map { it.name }}")
println("Common courses (Alice & Bob): ${courseManager.getCommonCourses(alice, bob).map { it.name }}")
println("All courses: ${courseManager.getAllCourses().map { it.name }}")
println("Students in Kotlin course: ${courseManager.getStudentsInCourse(kotlin).map { it.name }}")
// 6. Performance comparison demonstration
println("\n6. Performance Comparison:")
val testSize = 10000
// HashSet performance
val hashSetTest = hashSetOf<Int>()
val hashSetTime = measureTimeMillis {
repeat(testSize) { hashSetTest.add(Random.nextInt()) }
}
// LinkedHashSet performance
val linkedSetTest = linkedSetOf<Int>()
val linkedSetTime = measureTimeMillis {
repeat(testSize) { linkedSetTest.add(Random.nextInt()) }
}
// TreeSet performance
val treeSetTest = sortedSetOf<Int>()
val treeSetTime = measureTimeMillis {
repeat(testSize) { treeSetTest.add(Random.nextInt()) }
}
println("Performance for $testSize operations:")
println("HashSet: ${hashSetTime}ms")
println("LinkedHashSet: ${linkedSetTime}ms")
println("TreeSet: ${treeSetTime}ms")
println("\nSet sizes after operations:")
println("HashSet: ${hashSetTest.size}")
println("LinkedHashSet: ${linkedSetTest.size}")
println("TreeSet: ${treeSetTest.size}")
}
// Extension function for measuring time
fun measureTimeMillis(action: () -> Unit): Long {
val start = System.currentTimeMillis()
action()
return System.currentTimeMillis() - start
}
Expected Output:
=== Kotlin Set Comprehensive Example ===
1. Creating Different Set Types:
Immutable Set: [Red, Green, Blue]
Mutable Set: [1, 2, 3]
Hash Set: [Apple, Cherry, Banana]
Linked Set: [First, Second, Third]
Sorted Set: [1, 3, 5, 7, 9]
2. Set Operations:
After adding elements: [1, 2, 3, 4, 5, 6, 7]
After removing elements: [2, 3, 4, 5]
Contains 3: true
Contains 10: false
Set size: 4
Is empty: false
3. Mathematical Set Operations:
Frontend: [HTML, CSS, JavaScript, React]
Backend: [Kotlin, Java, Python, JavaScript]
Union: [HTML, CSS, JavaScript, React, Kotlin, Java, Python]
Intersection: [JavaScript]
Frontend - Backend: [HTML, CSS, React]
Symmetric Difference: [HTML, CSS, React, Kotlin, Java, Python]
4. Functional Operations:
Original: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Even numbers: [2, 4, 6, 8, 10]
Squared numbers: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Numbers > 5: [6, 7, 8, 9, 10]
Sum: 55, Max: 10, Min: 1, Average: 5.5
5. Student Course Management System:
Alice's courses: [Kotlin Programming, Android Development, Data Structures & Algorithms]
Bob's courses: [Kotlin Programming, Data Structures & Algorithms, Database Systems]
Charlie's courses: [Android Development, Database Systems]
Common courses (Alice & Bob): [Kotlin Programming, Data Structures & Algorithms]
All courses: [Kotlin Programming, Android Development, Data Structures & Algorithms, Database Systems]
Students in Kotlin course: [Alice, Bob]
6. Performance Comparison:
Performance for 10000 operations:
HashSet: 15ms
LinkedHashSet: 18ms
TreeSet: 45ms
Set sizes after operations:
HashSet: 9876
LinkedHashSet: 9823
TreeSet: 9901