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
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.
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
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]
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)
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
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)
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"
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]
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]}
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]
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]
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
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 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
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]
*/
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
*/
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
*/