Skip to content

Arrays and Collections

Overview

Kotlin provides rich array and collection types for storing and manipulating data. This chapter will detail arrays, lists, sets, maps, and other data structures, as well as their creation, operations, and best practices.

Arrays

Basic Array Operations

kotlin
fun main() {
    // Different ways to create arrays
    val numbers1 = arrayOf(1, 2, 3, 4, 5)
    val numbers2 = Array(5) { i -> i * 2 }  // [0, 2, 4, 6, 8]
    val numbers3 = Array(5) { 0 }           // [0, 0, 0, 0, 0]
    
    // Arrays with specified type
    val strings: Array<String> = arrayOf("apple", "banana", "cherry")
    val nullableStrings: Array<String?> = arrayOfNulls(3)
    
    println("Array creation:")
    println("numbers1: ${numbers1.contentToString()}")
    println("numbers2: ${numbers2.contentToString()}")
    println("strings: ${strings.contentToString()}")
    
    // Array access and modification
    println("\nArray access:")
    println("First element: ${numbers1[0]}")
    println("Last element: ${numbers1[numbers1.size - 1]}")
    println("Array length: ${numbers1.size}")
    
    // Modify array element
    numbers1[0] = 10
    println("After modification: ${numbers1.contentToString()}")
    
    // Safe access
    fun safeGet(array: Array<Int>, index: Int): Int? {
        return if (index in array.indices) array[index] else null
    }
    
    println("Safe access index 5: ${safeGet(numbers1, 5)}")
    println("Safe access index 2: ${safeGet(numbers1, 2)}")
}

Primitive Type Arrays

kotlin
fun main() {
    // Primitive type arrays (avoid boxing overhead)
    val intArray = intArrayOf(1, 2, 3, 4, 5)
    val doubleArray = doubleArrayOf(1.1, 2.2, 3.3)
    val booleanArray = booleanArrayOf(true, false, true)
    val charArray = charArrayOf('a', 'b', 'c')
    val longArray = LongArray(5) { it.toLong() * 10 }
    
    println("Primitive type arrays:")
    println("IntArray: ${intArray.contentToString()}")
    println("DoubleArray: ${doubleArray.contentToString()}")
    println("BooleanArray: ${booleanArray.contentToString()}")
    println("CharArray: ${charArray.contentToString()}")
    println("LongArray: ${longArray.contentToString()}")
    
    // Array operations
    println("\nArray operations:")
    println("Sum: ${intArray.sum()}")
    println("Average: ${intArray.average()}")
    println("Maximum: ${intArray.maxOrNull()}")
    println("Minimum: ${intArray.minOrNull()}")
    println("Sorted: ${intArray.sorted()}")
    
    // Array transformations
    val doubled = intArray.map { it * 2 }
    val filtered = intArray.filter { it > 2 }
    val exists = intArray.any { it > 4 }
    val allPositive = intArray.all { it > 0 }
    
    println("Doubled: $doubled")
    println("Filtered > 2: $filtered")
    println("Exists > 4: $exists")
    println("All positive: $allPositive")
}

Multidimensional Arrays

kotlin
fun main() {
    // 2D array
    val matrix = Array(3) { Array(3) { 0 } }
    val matrix2 = arrayOf(
        arrayOf(1, 2, 3),
        arrayOf(4, 5, 6),
        arrayOf(7, 8, 9)
    )
    
    // Initialize matrix
    for (i in matrix.indices) {
        for (j in matrix[i].indices) {
            matrix[i][j] = i * 3 + j + 1
        }
    }
    
    println("Matrix operations:")
    println("Matrix 1:")
    printMatrix(matrix)
    
    println("Matrix 2:")
    printMatrix(matrix2)
    
    // Matrix operations
    val sum = addMatrices(matrix, matrix2)
    println("Matrix addition:")
    printMatrix(sum)
    
    // Transpose matrix
    val transposed = transposeMatrix(matrix2)
    println("Transposed matrix:")
    printMatrix(transposed)
}

fun printMatrix(matrix: Array<Array<Int>>) {
    for (row in matrix) {
        println(row.joinToString(" ") { "%3d".format(it) })
    }
}

fun addMatrices(a: Array<Array<Int>>, b: Array<Array<Int>>): Array<Array<Int>> {
    require(a.size == b.size && a[0].size == b[0].size) { "Matrix dimensions don't match" }
    
    return Array(a.size) { i ->
        Array(a[i].size) { j ->
            a[i][j] + b[i][j]
        }
    }
}

fun transposeMatrix(matrix: Array<Array<Int>>): Array<Array<Int>> {
    val rows = matrix.size
    val cols = matrix[0].size
    
    return Array(cols) { j ->
        Array(rows) { i ->
            matrix[i][j]
        }
    }
}

Lists

Immutable Lists

kotlin
fun main() {
    // Create immutable lists
    val fruits = listOf("apple", "banana", "cherry", "date")
    val numbers = listOf(1, 2, 3, 4, 5)
    val mixed = listOf("hello", 42, 3.14, true)
    val emptyList = emptyList<String>()
    
    println("List creation:")
    println("Fruits: $fruits")
    println("Numbers: $numbers")
    println("Mixed: $mixed")
    
    // List access
    println("\nList access:")
    println("First fruit: ${fruits[0]}")
    println("First fruit (first): ${fruits.first()}")
    println("Last fruit: ${fruits.last()}")
    println("Second fruit (getOrNull): ${fruits.getOrNull(1)}")
    println("Index 10 (getOrNull): ${fruits.getOrNull(10)}")
    
    // List properties
    println("\nList properties:")
    println("Size: ${fruits.size}")
    println("Is empty: ${fruits.isEmpty()}")
    println("Contains 'apple': ${"apple" in fruits}")
    println("Contains 'grape': ${"grape" in fruits}")
    
    // List slicing
    println("\nList slicing:")
    println("First 3: ${fruits.take(3)}")
    println("Skip 2: ${fruits.drop(2)}")
    println("Sublist [1,3): ${fruits.subList(1, 3)}")
    
    // List searching
    println("\nList searching:")
    println("Index of 'cherry': ${fruits.indexOf("cherry")}")
    println("Index of 'grape': ${fruits.indexOf("grape")}")  // -1 means not found
    println("First starting with 'a': ${fruits.find { it.startsWith('a') }}")
    println("First with length > 5: ${fruits.find { it.length > 5 }}")
}

Mutable Lists

kotlin
fun main() {
    // Create mutable lists
    val mutableFruits = mutableListOf("apple", "banana")
    val arrayList = arrayListOf<String>()
    
    println("Mutable list operations:")
    println("Initial list: $mutableFruits")
    
    // Add elements
    mutableFruits.add("cherry")
    mutableFruits.add(1, "orange")  // Insert at specific position
    mutableFruits.addAll(listOf("grape", "kiwi"))
    
    println("After adding: $mutableFruits")
    
    // Remove elements
    mutableFruits.remove("banana")
    mutableFruits.removeAt(0)  // Remove at specific position
    mutableFruits.removeAll(listOf("grape", "kiwi"))
    
    println("After removing: $mutableFruits")
    
    // Modify elements
    mutableFruits[0] = "pineapple"
    println("After modification: $mutableFruits")
    
    // List operations
    mutableFruits.sort()
    println("After sorting: $mutableFruits")
    
    mutableFruits.reverse()
    println("After reversing: $mutableFruits")
    
    mutableFruits.shuffle()
    println("After shuffling: $mutableFruits")
    
    // Batch operations
    val numbers = mutableListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    numbers.removeIf { it % 2 == 0 }  // Remove even numbers
    println("After removing evens: $numbers")
    
    numbers.replaceAll { it * 2 }  // Double all elements
    println("After doubling: $numbers")
}

Functional Operations on Lists

kotlin
data class Person(val name: String, val age: Int, val city: String)

fun main() {
    val people = listOf(
        Person("Alice", 25, "New York"),
        Person("Bob", 30, "London"),
        Person("Charlie", 35, "Tokyo"),
        Person("Diana", 28, "New York"),
        Person("Eve", 32, "London")
    )
    
    println("Functional list operations:")
    
    // map - transformation
    val names = people.map { it.name }
    val ages = people.map { it.age }
    val nameAgeMap = people.map { "${it.name} (${it.age})" }
    
    println("Names: $names")
    println("Ages: $ages")
    println("Name-Age: $nameAgeMap")
    
    // filter - filtering
    val adults = people.filter { it.age >= 30 }
    val newYorkers = people.filter { it.city == "New York" }
    
    println("Age 30+: ${adults.map { it.name }}")
    println("New Yorkers: ${newYorkers.map { it.name }}")
    
    // groupBy - grouping
    val peopleByCity = people.groupBy { it.city }
    val peopleByAgeGroup = people.groupBy { 
        when {
            it.age < 30 -> "Young"
            it.age < 35 -> "Middle"
            else -> "Mature"
        }
    }
    
    println("Grouped by city:")
    peopleByCity.forEach { (city, cityPeople) ->
        println("  $city: ${cityPeople.map { it.name }}")
    }
    
    println("Grouped by age group:")
    peopleByAgeGroup.forEach { (ageGroup, agePeople) ->
        println("  $ageGroup: ${agePeople.map { it.name }}")
    }
    
    // Aggregation operations
    val totalAge = people.sumOf { it.age }
    val averageAge = people.map { it.age }.average()
    val oldestPerson = people.maxByOrNull { it.age }
    val youngestPerson = people.minByOrNull { it.age }
    
    println("Total age: $totalAge")
    println("Average age: ${"%.1f".format(averageAge)}")
    println("Oldest: ${oldestPerson?.name}")
    println("Youngest: ${youngestPerson?.name}")
    
    // Chain operations
    val result = people
        .filter { it.age >= 28 }
        .sortedBy { it.age }
        .groupBy { it.city }
        .mapValues { (_, cityPeople) -> cityPeople.map { it.name } }
    
    println("Chain operation result: $result")
}

Sets

Immutable Sets

kotlin
fun main() {
    // Create immutable sets
    val numbers = setOf(1, 2, 3, 4, 5, 3, 2, 1)  // Duplicates are removed
    val fruits = setOf("apple", "banana", "cherry")
    val emptySet = emptySet<String>()
    
    println("Set creation:")
    println("Number set: $numbers")  // [1, 2, 3, 4, 5]
    println("Fruit set: $fruits")
    println("Set size: ${numbers.size}")
    
    // Set checking
    println("\nSet checking:")
    println("Contains 3: ${3 in numbers}")
    println("Contains 6: ${6 in numbers}")
    println("Is empty: ${numbers.isEmpty()}")
    
    // Set operations
    val set1 = setOf(1, 2, 3, 4, 5)
    val set2 = setOf(4, 5, 6, 7, 8)
    
    println("\nSet operations:")
    println("set1: $set1")
    println("set2: $set2")
    println("Union: ${set1 union set2}")
    println("Intersection: ${set1 intersect set2}")
    println("Difference: ${set1 - set2}")
    println("Symmetric difference: ${(set1 - set2) + (set2 - set1)}")
    
    // Subset check
    val subset = setOf(2, 3)
    println("$subset is subset of $set1: ${subset.all { it in set1 }}")
    
    // Set transformations
    val doubled = numbers.map { it * 2 }.toSet()
    val filtered = numbers.filter { it > 2 }.toSet()
    
    println("\nSet transformations:")
    println("Doubled: $doubled")
    println("Filtered > 2: $filtered")
}

Mutable Sets

kotlin
fun main() {
    // Create mutable sets
    val mutableNumbers = mutableSetOf(1, 2, 3)
    val hashSet = hashSetOf<String>()
    val linkedHashSet = linkedSetOf<String>()  // Maintains insertion order
    
    println("Mutable set operations:")
    println("Initial set: $mutableNumbers")
    
    // Add elements
    mutableNumbers.add(4)
    mutableNumbers.add(2)  // Duplicate won't be added
    mutableNumbers.addAll(setOf(5, 6, 7))
    
    println("After adding: $mutableNumbers")
    
    // Remove elements
    mutableNumbers.remove(3)
    mutableNumbers.removeAll(setOf(6, 7))
    
    println("After removing: $mutableNumbers")
    
    // Retain operation
    mutableNumbers.retainAll(setOf(1, 2, 4, 8))  // Keep only specified elements
    println("After retaining: $mutableNumbers")
    
    // LinkedHashSet example (maintains insertion order)
    linkedHashSet.addAll(listOf("third", "first", "second"))
    println("LinkedHashSet: $linkedHashSet")  // Maintains insertion order
    
    // HashSet example (no guaranteed order)
    hashSet.addAll(listOf("third", "first", "second"))
    println("HashSet: $hashSet")  // Order may differ
}

Maps

Immutable Maps

kotlin
fun main() {
    // Create immutable maps
    val capitals = mapOf(
        "USA" to "Washington",
        "UK" to "London",
        "Japan" to "Tokyo",
        "France" to "Paris"
    )
    
    val numbers = mapOf(1 to "one", 2 to "two", 3 to "three")
    val emptyMap = emptyMap<String, String>()
    
    println("Map creation:")
    println("Capitals: $capitals")
    println("Numbers: $numbers")
    
    // Map access
    println("\nMap access:")
    println("Capital of USA: ${capitals["USA"]}")
    println("Capital of China: ${capitals["China"]}")  // null
    println("Capital of UK (getValue): ${capitals.getValue("UK")}")
    println("Capital of Germany (getOrDefault): ${capitals.getOrDefault("Germany", "Unknown")}")
    
    // Map properties
    println("\nMap properties:")
    println("Size: ${capitals.size}")
    println("Is empty: ${capitals.isEmpty()}")
    println("Contains key 'Japan': ${"Japan" in capitals}")
    println("Contains value 'Berlin': ${"Berlin" in capitals.values}")
    
    // Keys and values
    println("\nKeys and values:")
    println("All keys: ${capitals.keys}")
    println("All values: ${capitals.values}")
    println("All entries: ${capitals.entries}")
    
    // Map traversal
    println("\nMap traversal:")
    for ((country, capital) in capitals) {
        println("Capital of $country is $capital")
    }
    
    capitals.forEach { (country, capital) ->
        println("$country -> $capital")
    }
}

Mutable Maps

kotlin
fun main() {
    // Create mutable maps
    val mutableScores = mutableMapOf(
        "Alice" to 95,
        "Bob" to 87,
        "Charlie" to 92
    )
    
    val hashMap = hashMapOf<String, Int>()
    val linkedHashMap = linkedMapOf<String, Int>()  // Maintains insertion order
    
    println("Mutable map operations:")
    println("Initial scores: $mutableScores")
    
    // Add and modify
    mutableScores["Diana"] = 89  // Add new entry
    mutableScores["Alice"] = 98  // Modify existing entry
    mutableScores.put("Eve", 91)
    mutableScores.putAll(mapOf("Frank" to 85, "Grace" to 94))
    
    println("After adding: $mutableScores")
    
    // Remove
    mutableScores.remove("Bob")
    val removedScore = mutableScores.remove("Charlie")
    println("Removed Charlie's score: $removedScore")
    
    println("After removing: $mutableScores")
    
    // Conditional operations
    mutableScores.putIfAbsent("Alice", 100)  // Add only if not exists
    mutableScores.replace("Diana", 89, 90)   // Conditional replacement
    
    println("After conditional operations: $mutableScores")
    
    // Compute operations
    mutableScores.compute("Alice") { _, oldValue -> (oldValue ?: 0) + 2 }
    mutableScores.computeIfAbsent("Henry") { 88 }
    mutableScores.computeIfPresent("Eve") { _, oldValue -> oldValue + 5 }
    
    println("After compute operations: $mutableScores")
    
    // Merge operation
    mutableScores.merge("Grace", 10) { oldValue, newValue -> oldValue + newValue }
    
    println("After merge operation: $mutableScores")
}

Advanced Map Operations

kotlin
data class Student(val name: String, val grade: Int, val subject: String)

fun main() {
    val students = listOf(
        Student("Alice", 95, "Math"),
        Student("Bob", 87, "Math"),
        Student("Charlie", 92, "Science"),
        Student("Diana", 89, "Math"),
        Student("Eve", 91, "Science"),
        Student("Frank", 85, "English"),
        Student("Grace", 94, "English")
    )
    
    println("Advanced map operations:")
    
    // Group by subject
    val studentsBySubject = students.groupBy { it.subject }
    println("Grouped by subject:")
    studentsBySubject.forEach { (subject, subjectStudents) ->
        println("  $subject: ${subjectStudents.map { it.name }}")
    }
    
    // Create name to grade mapping
    val nameToGrade = students.associate { it.name to it.grade }
    println("\nName to grade mapping: $nameToGrade")
    
    // Calculate average by subject
    val averageBySubject = students
        .groupBy { it.subject }
        .mapValues { (_, subjectStudents) -> 
            subjectStudents.map { it.grade }.average()
        }
    
    println("Average by subject:")
    averageBySubject.forEach { (subject, average) ->
        println("  $subject: ${"%.1f".format(average)}")
    }
    
    // Map transformation
    val gradeDistribution = students
        .groupingBy { 
            when {
                it.grade >= 90 -> "A"
                it.grade >= 80 -> "B"
                it.grade >= 70 -> "C"
                else -> "D"
            }
        }
        .eachCount()
    
    println("Grade distribution: $gradeDistribution")
    
    // Map filtering
    val highPerformers = nameToGrade.filter { (_, grade) -> grade >= 90 }
    val mathStudents = studentsBySubject["Math"]?.associate { it.name to it.grade } ?: emptyMap()
    
    println("High performers: $highPerformers")
    println("Math students: $mathStudents")
    
    // Map merging
    val bonusPoints = mapOf("Alice" to 5, "Bob" to 3, "Charlie" to 2)
    val finalGrades = nameToGrade.toMutableMap()
    
    bonusPoints.forEach { (name, bonus) ->
        finalGrades.merge(name, bonus) { oldGrade, bonusPoint -> oldGrade + bonusPoint }
    }
    
    println("Final grades with bonus: $finalGrades")
}

Sequences

Lazy Evaluation

kotlin
fun main() {
    // Sequence vs Collection performance comparison
    val largeList = (1..1_000_000).toList()
    
    println("Sequence operations:")
    
    // Using collection (eager evaluation)
    val listResult = largeList
        .filter { it % 2 == 0 }
        .map { it * it }
        .take(10)
    
    println("Collection result: $listResult")
    
    // Using sequence (lazy evaluation)
    val sequenceResult = largeList.asSequence()
        .filter { it % 2 == 0 }
        .map { it * it }
        .take(10)
        .toList()
    
    println("Sequence result: $sequenceResult")
    
    // Creating sequences
    val sequence1 = sequenceOf(1, 2, 3, 4, 5)
    val sequence2 = generateSequence(1) { it + 1 }  // Infinite sequence
    val sequence3 = generateSequence { kotlin.random.Random.nextInt(100) }
    
    println("Sequence 1 first 5: ${sequence1.take(5).toList()}")
    println("Sequence 2 first 10: ${sequence2.take(10).toList()}")
    println("Sequence 3 first 5: ${sequence3.take(5).toList()}")
    
    // Fibonacci sequence
    val fibonacci = generateSequence(Pair(0, 1)) { (a, b) -> Pair(b, a + b) }
        .map { it.first }
    
    println("Fibonacci first 15: ${fibonacci.take(15).toList()}")
    
    // File processing example (simulated)
    fun processLargeDataset(): Sequence<String> = sequence {
        repeat(1000) { index ->
            yield("Data row $index")
            // Simulate reading from file or database
        }
    }
    
    val processedData = processLargeDataset()
        .filter { it.contains("5") }
        .map { it.uppercase() }
        .take(5)
        .toList()
    
    println("Processed data: $processedData")
}

Practical Applications

Data Analysis Example

kotlin
data class SalesRecord(
    val date: String,
    val product: String,
    val category: String,
    val amount: Double,
    val quantity: Int,
    val region: String
)

class SalesAnalyzer {
    fun analyzeSales(records: List<SalesRecord>): Map<String, Any> {
        val totalSales = records.sumOf { it.amount }
        val totalQuantity = records.sumOf { it.quantity }
        val averageOrderValue = totalSales / records.size
        
        // Analyze by product
        val salesByProduct = records
            .groupBy { it.product }
            .mapValues { (_, productRecords) -> 
                productRecords.sumOf { it.amount }
            }
            .toList()
            .sortedByDescending { it.second }
        
        // Analyze by category
        val salesByCategory = records
            .groupBy { it.category }
            .mapValues { (_, categoryRecords) ->
                mapOf(
                    "totalSales" to categoryRecords.sumOf { it.amount },
                    "totalQuantity" to categoryRecords.sumOf { it.quantity },
                    "averagePrice" to categoryRecords.map { it.amount / it.quantity }.average()
                )
            }
        
        // Analyze by region
        val salesByRegion = records
            .groupBy { it.region }
            .mapValues { (_, regionRecords) -> regionRecords.sumOf { it.amount } }
        
        // Trend analysis
        val salesByDate = records
            .groupBy { it.date }
            .mapValues { (_, dateRecords) -> dateRecords.sumOf { it.amount } }
            .toSortedMap()
        
        return mapOf(
            "totalSales" to totalSales,
            "totalQuantity" to totalQuantity,
            "averageOrderValue" to averageOrderValue,
            "topProducts" to salesByProduct.take(5),
            "categoryAnalysis" to salesByCategory,
            "regionAnalysis" to salesByRegion,
            "dailyTrend" to salesByDate
        )
    }
}

fun main() {
    val salesRecords = listOf(
        SalesRecord("2023-01-01", "Laptop", "Electronics", 999.99, 1, "Beijing"),
        SalesRecord("2023-01-01", "Mouse", "Electronics", 29.99, 2, "Shanghai"),
        SalesRecord("2023-01-02", "Keyboard", "Electronics", 79.99, 1, "Guangzhou"),
        SalesRecord("2023-01-02", "Monitor", "Electronics", 299.99, 1, "Shenzhen"),
        SalesRecord("2023-01-03", "Coffee", "Food", 15.99, 3, "Beijing"),
        SalesRecord("2023-01-03", "Tea", "Food", 25.99, 2, "Shanghai"),
        SalesRecord("2023-01-04", "Laptop", "Electronics", 1199.99, 1, "Guangzhou"),
        SalesRecord("2023-01-04", "Phone", "Electronics", 699.99, 1, "Shenzhen")
    )
    
    val analyzer = SalesAnalyzer()
    val analysis = analyzer.analyzeSales(salesRecords)
    
    println("Sales Data Analysis Report:")
    println("Total sales: ${"%.2f".format(analysis["totalSales"])}")
    println("Total quantity: ${analysis["totalQuantity"]}")
    println("Average order value: ${"%.2f".format(analysis["averageOrderValue"])}")
    
    println("\nTop 5 Products:")
    @Suppress("UNCHECKED_CAST")
    val topProducts = analysis["topProducts"] as List<Pair<String, Double>>
    topProducts.forEach { (product, sales) ->
        println("  $product: ${"%.2f".format(sales)}")
    }
    
    println("\nCategory Analysis:")
    @Suppress("UNCHECKED_CAST")
    val categoryAnalysis = analysis["categoryAnalysis"] as Map<String, Map<String, Any>>
    categoryAnalysis.forEach { (category, stats) ->
        println("  $category:")
        println("    Total sales: ${"%.2f".format(stats["totalSales"])}")
        println("    Total quantity: ${stats["totalQuantity"]}")
        println("    Average price: ${"%.2f".format(stats["averagePrice"])}")
    }
}

Performance Optimization

Collection Selection Guide

kotlin
fun main() {
    println("Collection performance guide:")
    
    // 1. Choose appropriate collection type based on use case
    
    // Need to maintain insertion order and allow duplicates -> List
    val orderHistory = mutableListOf<String>()
    
    // Need uniqueness and don't care about order -> HashSet
    val uniqueVisitors = hashSetOf<String>()
    
    // Need uniqueness and maintain insertion order -> LinkedHashSet
    val orderedCategories = linkedSetOf<String>()
    
    // Need key-value mapping and don't care about order -> HashMap
    val userCache = hashMapOf<String, Any>()
    
    // Need key-value mapping and maintain insertion order -> LinkedHashMap
    val orderedConfig = linkedMapOf<String, String>()
    
    // 2. Use sequences for large data processing
    fun processLargeDataEfficiently(data: List<Int>): List<Int> {
        return data.asSequence()
            .filter { it > 100 }
            .map { it * 2 }
            .take(1000)
            .toList()
    }
    
    // 3. Avoid unnecessary intermediate collections
    val numbers = (1..1000).toList()
    
    // Bad: creates multiple intermediate collections
    val result1 = numbers
        .filter { it % 2 == 0 }
        .map { it * it }
        .filter { it > 100 }
        .sorted()
    
    // Good: use sequence to reduce intermediate collections
    val result2 = numbers.asSequence()
        .filter { it % 2 == 0 }
        .map { it * it }
        .filter { it > 100 }
        .sorted()
        .toList()
    
    println("Optimized result size: ${result2.size}")
}

Best Practices

1. Choose Appropriate Collection Types

kotlin
// Choose collection type based on requirements
class BestPractices {
    
    // Use immutable collections for read-only data
    val supportedLanguages = listOf("Kotlin", "Java", "Python", "JavaScript")
    
    // Use mutable collections for data that needs modification
    private val _activeUsers = mutableSetOf<String>()
    val activeUsers: Set<String> = _activeUsers  // Expose read-only view
    
    // Use sequences for large datasets
    fun processLargeDataset(data: List<String>): List<String> {
        return data.asSequence()
            .filter { it.isNotBlank() }
            .map { it.trim().lowercase() }
            .distinct()
            .sorted()
            .toList()
    }
    
    // Use appropriate collection operations
    fun findUsersByCity(users: List<Person>, city: String): List<Person> {
        return users.filter { it.city == city }  // Instead of manual loop
    }
}

2. Null Safety and Error Handling

kotlin
fun safeCollectionOperations() {
    val numbers: List<Int>? = null
    val emptyList = emptyList<Int>()
    val normalList = listOf(1, 2, 3, 4, 5)
    
    // Safe access
    println("First element of null list: ${numbers?.firstOrNull()}")
    println("Size of null list: ${numbers?.size ?: 0}")
    
    // Use safe operations
    val result = normalList
        .takeIf { it.isNotEmpty() }
        ?.filter { it > 2 }
        ?.map { it * 2 }
        ?: emptyList()
    
    println("Safe operation result: $result")
}

Next Steps

After mastering arrays and collections, let's learn about interfaces and abstract classes in Kotlin.

Next Chapter: Interfaces and Abstract Classes

Exercises

  1. Implement a student grade management system using different collection types to store data
  2. Create a library management system that supports CRUD operations for books
  3. Write a data analysis tool that processes large sales data and generates reports
  4. Implement a caching system using maps to store key-value pairs with expiration time support
  5. Design a recommendation system based on user behavior data

Content is for learning and research only.