Kotlin List

A Kotlin list is a generic, ordered collection interface that stores elements in a specific sequence. Lists maintain insertion order and allow duplicate elements, making them perfect for scenarios where element position matters. The List interface in Kotlin extends the Collection interface and provides indexed access to elements, starting from index 0.

// Basic list structure  
val numbers: List<Int> = listOf(1, 2, 3, 4, 5)  
val firstElement = numbers[0] // Access by index  
val listSize = numbers.size   // Get list size  

Key Characteristics of Kotlin Lists

Ordered Collection: Elements maintain their insertion order, ensuring predictable iteration and access patterns.

Index-Based Access: Elements can be accessed directly using their zero-based index position.

Duplicate Elements Allowed: Unlike sets, lists can contain multiple instances of the same element.

Type Safety: Kotlin’s type system ensures compile-time safety when working with list elements.

Creating Immutable Lists with listOf()

Basic listOf() Usage

The listOf() function creates read-only lists that cannot be modified after creation. This immutability provides thread safety and prevents accidental modifications that could lead to bugs.

// Creating different types of immutable lists  
val fruits = listOf("apple", "banana", "orange")  
val primes = listOf(2, 3, 5, 7, 11)  
val mixedTypes = listOf("text", 42, true, 3.14)  
val emptyList = listOf<String>() // Empty typed list  

Advanced listOf() Patterns

Null Handling with listOfNotNull():

val validItems = listOfNotNull("item1", null, "item3", null, "item5")  
// Result: ["item1", "item3", "item5"]  

Creating Lists with Repeated Elements:

val repeatedElements = List(5) { "default" }  
// Result: ["default", "default", "default", "default", "default"]  

List Creation with Lambda Initialization:

val squaredNumbers = List(10) { index -> index * index }  
// Result: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]  

Working with Mutable Lists using mutableListOf()

Creating and Modifying Mutable Lists

MutableListOf() creates lists that support add, remove, and update operations. These lists implement the MutableList interface, providing full read-write capabilities.

// Creating mutable lists  
val cities = mutableListOf("New York", "London", "Tokyo")  
val numbers = mutableListOf<Int>() // Empty mutable list  
val mixedData = mutableListOf<Any>("text", 123, true)  

Essential Mutable List Operations

Adding Elements:

val shoppingList = mutableListOf("milk", "bread")  
shoppingList.add("eggs")                    // Add at end  
shoppingList.add(1, "butter")              // Add at specific index  
shoppingList.addAll(listOf("cheese", "ham")) // Add multiple elements  
shoppingList += "yogurt"                   // Operator overloading  

Removing Elements:

val items = mutableListOf("a", "b", "c", "d", "b")  
items.remove("b")           // Removes first occurrence  
items.removeAt(2)          // Remove by index  
items.removeAll(listOf("a", "c")) // Remove multiple elements  
items.clear()              // Remove all elements  

Updating Elements:

val scores = mutableListOf(85, 92, 78, 96)  
scores[1] = 95            // Update using index operator  
scores.set(3, 100)        // Update using set method  
scores.fill(0)            // Replace all elements with same value  

Essential List Access Methods

Element Retrieval Techniques

Safe Access Methods:

val languages = listOf("Kotlin", "Java", "Swift", "Python")  
  
// Safe access with bounds checking  
val first = languages.getOrNull(0)      // Returns "Kotlin" or null  
val invalid = languages.getOrNull(10)   // Returns null  
val withDefault = languages.getOrElse(5) { "Unknown" } // Returns "Unknown"  

First and Last Element Access:

val scores = listOf(88, 92, 78, 96, 85)  
val highest = scores.first()             // First element: 88  
val lowest = scores.last()               // Last element: 85  
val firstHigh = scores.first { it > 90 } // First element > 90: 92  
val lastHigh = scores.lastOrNull { it > 100 } // null (no element > 100)  

Index Operations

Finding Element Positions:

val colors = listOf("red", "blue", "green", "blue", "yellow")  
val firstBlue = colors.indexOf("blue")        // Returns 1  
val lastBlue = colors.lastIndexOf("blue")     // Returns 3  
val notFound = colors.indexOf("purple")       // Returns -1  
  
// Conditional index finding  
val firstLongColor = colors.indexOfFirst { it.length > 4 }  // Index of "green"  
val lastLongColor = colors.indexOfLast { it.length > 4 }    // Index of "yellow"  

Advanced List Transformation Methods

Mapping and Filtering Operations

Transform Elements with map():

val temperatures = listOf(20, 25, 30, 35)  
val fahrenheit = temperatures.map { celsius -> celsius * 9/5 + 32 }  
// Result: [68, 77, 86, 95]  
  
val names = listOf("john", "alice", "bob")  
val capitalized = names.map { it.replaceFirstChar { char -> char.uppercase() } }  
// Result: ["John", "Alice", "Bob"]  

Filter Elements with Conditions:

val ages = listOf(16, 25, 19, 30, 15, 28)  
val adults = ages.filter { it >= 18 }           // [25, 19, 30, 28]  
val minors = ages.filterNot { it >= 18 }        // [16, 15]  
val evenAges = ages.filter { it % 2 == 0 }      // [16, 30, 28]  

Partitioning and Grouping

Partition Elements:

val grades = listOf(85, 92, 67, 88, 91, 73, 96)  
val (passing, failing) = grades.partition { it >= 75 }  
// passing: [85, 92, 88, 91, 96], failing: [67, 73]  

Group by Criteria:

val students = listOf("Alice", "Bob", "Charlie", "Diana", "Alex")  
val byFirstLetter = students.groupBy { it.first() }  
// Result: {A=[Alice, Alex], B=[Bob], C=[Charlie], D=[Diana]}  

List Slicing and Sublist Operations

Creating Sublists

Using take() and drop() Methods:

val fibonacci = listOf(1, 1, 2, 3, 5, 8, 13, 21, 34)  
val firstFive = fibonacci.take(5)           // [1, 1, 2, 3, 5]  
val lastFour = fibonacci.takeLast(4)        // [8, 13, 21, 34]  
val skipFirst = fibonacci.drop(2)           // [2, 3, 5, 8, 13, 21, 34]  
val skipLast = fibonacci.dropLast(3)        // [1, 1, 2, 3, 5, 8]  

Conditional Taking and Dropping:

val numbers = listOf(1, 3, 5, 8, 10, 12, 15)  
val takeWhileOdd = numbers.takeWhile { it % 2 == 1 }  // [1, 3, 5]  
val dropWhileOdd = numbers.dropWhile { it % 2 == 1 }  // [8, 10, 12, 15]  

Range-based Sublists:

val alphabet = listOf('a', 'b', 'c', 'd', 'e', 'f', 'g')  
val middleSection = alphabet.subList(2, 5)  // [c, d, e]  
val sliceRange = alphabet.slice(1..4)       // [b, c, d, e]  
val specificIndices = alphabet.slice(listOf(0, 2, 4, 6)) // [a, c, e, g]  

List Sorting and Ordering

Sorting Immutable Lists

Basic Sorting Operations:

val unsorted = listOf(42, 17, 89, 23, 56)  
val ascending = unsorted.sorted()           // [17, 23, 42, 56, 89]  
val descending = unsorted.sortedDescending() // [89, 56, 42, 23, 17]  
  
val words = listOf("elephant", "cat", "butterfly", "dog")  
val byLength = words.sortedBy { it.length }  // [cat, dog, elephant, butterfly]  
val byLengthDesc = words.sortedByDescending { it.length } // [butterfly, elephant, cat, dog]  

In-Place Sorting for Mutable Lists

Modifying Original List:

val mutableScores = mutableListOf(88, 72, 95, 81, 90)  
mutableScores.sort()                    // Sorts in-place: [72, 81, 88, 90, 95]  
mutableScores.sortDescending()          // [95, 90, 88, 81, 72]  
  
val mutableNames = mutableListOf("Zoe", "Alice", "Bob", "Charlie")  
mutableNames.sortBy { it.length }       // Sort by length in-place  
mutableNames.sortWith(compareBy { it.lowercase() }) // Custom comparator  

List Aggregation and Statistical Operations

Mathematical Operations

Basic Statistics:

val values = listOf(10, 25, 30, 15, 40, 35, 20)  
val total = values.sum()               // 175  
val average = values.average()         // 25.0  
val maximum = values.maxOrNull()       // 40  
val minimum = values.minOrNull()       // 10  
val count = values.count()             // 7  

Custom Aggregation with reduce() and fold():

val numbers = listOf(1, 2, 3, 4, 5)  
val product = numbers.reduce { acc, n -> acc * n }    // 120  
val concatenated = numbers.fold("") { acc, n -> acc + n } // "12345"  
  
// Finding custom maximum  
data class Product(val name: String, val price: Double)  
val products = listOf(  
    Product("Laptop", 999.99),  
    Product("Mouse", 29.99),   
    Product("Keyboard", 79.99)  
)  
val mostExpensive = products.maxByOrNull { it.price } // Laptop  

Converting Between List Types

Transformation Methods

Converting to Different List Types:

val originalList = listOf(1, 2, 3, 4, 5)  
val mutableCopy = originalList.toMutableList()  
val immutableCopy = mutableCopy.toList()  
val arrayList = originalList.toCollection(ArrayList())  
val linkedList = originalList.toCollection(LinkedList())  

Type Conversion:

val strings = listOf("1", "2", "3", "4", "5")  
val integers = strings.map { it.toInt() }           // Convert to Int  
val doubled = strings.mapNotNull { it.toIntOrNull()?.times(2) } // Safe conversion  
  
// Converting to other collections  
val setFromList = originalList.toSet()              // Remove duplicates  
val arrayFromList = originalList.toTypedArray()     // Convert to Array  

Complete Working Examples

Example 1: Student Grade Management System

data class Student(val name: String, val grades: MutableList<Int>)  
  
fun main() {  
    // Initialize students with grades  
    val students = mutableListOf(  
        Student("Alice", mutableListOf(85, 92, 78, 88)),  
        Student("Bob", mutableListOf(79, 84, 91, 77)),  
        Student("Charlie", mutableListOf(92, 88, 94, 90))  
    )  
      
    // Add new grade for Alice  
    students[0].grades.add(95)  
      
    // Calculate averages for each student  
    val studentAverages = students.map { student ->  
        student.name to student.grades.average()  
    }  
      
    // Find top performing student  
    val topStudent = students.maxByOrNull { it.grades.average() }  
      
    // Filter students with average above 85  
    val highPerformers = students.filter { it.grades.average() > 85.0 }  
      
    // Print results  
    println("Student Averages:")  
    studentAverages.forEach { (name, avg) ->  
        println("$name: ${String.format("%.2f", avg)}")  
    }  
      
    println("\nTop Student: ${topStudent?.name}")  
    println("High Performers: ${highPerformers.map { it.name }}")  
}  
  
/* Expected Output:  
Student Averages:  
Alice: 87.60  
Bob: 82.75  
Charlie: 91.00  
  
Top Student: Charlie  
High Performers: [Alice, Charlie]  
*/  

Example 2: E-commerce Shopping Cart Implementation

data class Product(val id: Int, val name: String, val price: Double)  
data class CartItem(val product: Product, var quantity: Int)  
  
class ShoppingCart {  
    private val items = mutableListOf<CartItem>()  
      
    fun addProduct(product: Product, quantity: Int = 1) {  
        val existingItem = items.find { it.product.id == product.id }  
        if (existingItem != null) {  
            existingItem.quantity += quantity  
        } else {  
            items.add(CartItem(product, quantity))  
        }  
    }  
      
    fun removeProduct(productId: Int) {  
        items.removeAll { it.product.id == productId }  
    }  
      
    fun updateQuantity(productId: Int, newQuantity: Int) {  
        items.find { it.product.id == productId }?.quantity = newQuantity  
    }  
      
    fun getTotalPrice(): Double = items.sumOf { it.product.price * it.quantity }  
      
    fun getItems(): List<CartItem> = items.toList() // Return immutable view  
      
    fun getItemCount(): Int = items.sumOf { it.quantity }  
      
    fun getMostExpensiveItem(): CartItem? = items.maxByOrNull { it.product.price }  
      
    fun filterByPriceRange(minPrice: Double, maxPrice: Double): List<CartItem> {  
        return items.filter { it.product.price in minPrice..maxPrice }  
    }  
}  
  
fun main() {  
    val cart = ShoppingCart()  
      
    // Sample products  
    val laptop = Product(1, "Gaming Laptop", 1299.99)  
    val mouse = Product(2, "Wireless Mouse", 79.99)  
    val keyboard = Product(3, "Mechanical Keyboard", 149.99)  
    val monitor = Product(4, "4K Monitor", 399.99)  
      
    // Add products to cart  
    cart.addProduct(laptop, 1)  
    cart.addProduct(mouse, 2)  
    cart.addProduct(keyboard, 1)  
    cart.addProduct(monitor, 1)  
      
    // Update quantity  
    cart.updateQuantity(2, 3) // Change mouse quantity to 3  
      
    // Display cart information  
    println("Shopping Cart Contents:")  
    cart.getItems().forEach { item ->  
        val total = item.product.price * item.quantity  
        println("${item.product.name} x ${item.quantity} = $${String.format("%.2f", total)}")  
    }  
      
    println("\nCart Summary:")  
    println("Total Items: ${cart.getItemCount()}")  
    println("Total Price: $${String.format("%.2f", cart.getTotalPrice())}")  
      
    val mostExpensive = cart.getMostExpensiveItem()  
    println("Most Expensive Item: ${mostExpensive?.product?.name}")  
      
    // Filter affordable items (under $200)  
    val affordableItems = cart.filterByPriceRange(0.0, 200.0)  
    println("\nAffordable Items (under $200):")  
    affordableItems.forEach { item ->  
        println("- ${item.product.name}: $${item.product.price}")  
    }  
}  
  
/* Expected Output:  
Shopping Cart Contents:  
Gaming Laptop x 1 = $1299.99  
Wireless Mouse x 3 = $239.97  
Mechanical Keyboard x 1 = $149.99  
4K Monitor x 1 = $399.99  
  
Cart Summary:  
Total Items: 6  
Total Price: $2089.94  
Most Expensive Item: Gaming Laptop  
  
Affordable Items (under $200):  
- Wireless Mouse: $79.99  
- Mechanical Keyboard: $149.99  
*/  

Example 3: Data Processing Pipeline

data class Transaction(  
    val id: String,  
    val amount: Double,  
    val category: String,  
    val date: String,  
    val isCredit: Boolean  
)  
  
fun main() {  
    // Sample transaction data  
    val transactions = listOf(  
        Transaction("T001", 1200.00, "Salary", "2024-01-15", true),  
        Transaction("T002", 85.50, "Groceries", "2024-01-16", false),  
        Transaction("T003", 45.00, "Gas", "2024-01-17", false),  
        Transaction("T004", 1500.00, "Freelance", "2024-01-18", true),  
        Transaction("T005", 120.00, "Utilities", "2024-01-19", false),  
        Transaction("T006", 250.00, "Shopping", "2024-01-20", false),  
        Transaction("T007", 800.00, "Bonus", "2024-01-21", true),  
        Transaction("T008", 95.75, "Groceries", "2024-01-22", false)  
    )  
      
    // Separate credits and debits  
    val (credits, debits) = transactions.partition { it.isCredit }  
      
    // Calculate totals  
    val totalIncome = credits.sumOf { it.amount }  
    val totalExpenses = debits.sumOf { it.amount }  
    val netBalance = totalIncome - totalExpenses  
      
    // Group expenses by category  
    val expensesByCategory = debits.groupBy { it.category }  
        .mapValues { (_, transactions) -> transactions.sumOf { it.amount } }  
        .toList()  
        .sortedByDescending { it.second }  
      
    // Find largest transactions  
    val largestCredit = credits.maxByOrNull { it.amount }  
    val largestDebit = debits.maxByOrNull { it.amount }  
      
    // Filter high-value transactions (over $100)  
    val highValueTransactions = transactions.filter { it.amount > 100.0 }  
        .sortedByDescending { it.amount }  
      
    // Generate expense categories list  
    val uniqueCategories = debits.map { it.category }.distinct().sorted()  
      
    // Print financial summary  
    println("=== FINANCIAL SUMMARY ===")  
    println("Total Income: $${String.format("%.2f", totalIncome)}")  
    println("Total Expenses: $${String.format("%.2f", totalExpenses)}")  
    println("Net Balance: $${String.format("%.2f", netBalance)}")  
      
    println("\n=== EXPENSES BY CATEGORY ===")  
    expensesByCategory.forEach { (category, amount) ->  
        println("$category: $${String.format("%.2f", amount)}")  
    }  
      
    println("\n=== LARGEST TRANSACTIONS ===")  
    println("Largest Credit: ${largestCredit?.let { "${it.category} - $${it.amount}" }}")  
    println("Largest Debit: ${largestDebit?.let { "${it.category} - $${it.amount}" }}")  
      
    println("\n=== HIGH-VALUE TRANSACTIONS (>$100) ===")  
    highValueTransactions.forEach { transaction ->  
        val type = if (transaction.isCredit) "Credit" else "Debit"  
        println("${transaction.date}: $type - ${transaction.category} - $${transaction.amount}")  
    }  
      
    println("\n=== EXPENSE CATEGORIES ===")  
    println("Categories: ${uniqueCategories.joinToString(", ")}")  
      
    println("\n=== TRANSACTION STATISTICS ===")  
    println("Total Transactions: ${transactions.size}")  
    println("Credit Transactions: ${credits.size}")  
    println("Debit Transactions: ${debits.size}")  
    println("Average Transaction Amount: $${String.format("%.2f", transactions.map { it.amount }.average())}")  
}  
  
/* Expected Output:  
=== FINANCIAL SUMMARY ===  
Total Income: $3500.00  
Total Expenses: $596.25  
Net Balance: $2903.75  
  
=== EXPENSES BY CATEGORY ===  
Shopping: $250.00  
Groceries: $181.25  
Utilities: $120.00  
Gas: $45.00  
  
=== LARGEST TRANSACTIONS ===  
Largest Credit: Freelance - $1500.0  
Largest Debit: Shopping - $250.0  
  
=== HIGH-VALUE TRANSACTIONS (>$100) ===  
2024-01-18: Credit - Freelance - $1500.0  
2024-01-15: Credit - Salary - $1200.0  
2024-01-21: Credit - Bonus - $800.0  
2024-01-20: Debit - Shopping - $250.0  
2024-01-19: Debit - Utilities - $120.0  
  
=== EXPENSE CATEGORIES ===  
Categories: Gas, Groceries, Shopping, Utilities  
  
=== TRANSACTION STATISTICS ===  
Total Transactions: 8  
Credit Transactions: 3  
Debit Transactions: 5  
Average Transaction Amount: $512.03  
*/