Kotlin arrays represent fixed-size collections that hold elements of the same type or its subtypes. Unlike dynamic collections, Kotlin arrays maintain a constant size once initialized, making them ideal for performance-critical applications where memory allocation predictability matters. The Array class in Kotlin provides the foundation for all array operations, offering type safety and null safety features that distinguish it from traditional Java arrays.
Kotlin arrays are invariant, meaning you cannot assign an Array<String> to an Array<Any> to prevent runtime failures. This design choice ensures type safety throughout your application, making Kotlin arrays more reliable than their Java counterparts.
The arrayOf() function is the most straightforward way to create Kotlin arrays with known values:
val studentNames = arrayOf("Alice", "Bob", "Charlie", "Diana")
val examScores = arrayOf(95, 87, 92, 88)
val isActive = arrayOf(true, false, true, true)
The Array constructor accepts two parameters: array size and an initialization function:
val fibonacci = Array(10) { i ->
when (i) {
0, 1 -> 1
else -> fibonacci[i-1] + fibonacci[i-2]
}
}
For scenarios requiring empty arrays, use the emptyArray() function:
val emptyStringArray: Array<String> = emptyArray()
val emptyIntArray: Array<Int> = emptyArray()
When you need arrays filled with null values initially:
val placeholderArray = arrayOfNulls<String>(5)
// Creates: [null, null, null, null, null]
Kotlin provides specialized array classes for primitive types to avoid boxing overhead:
val numbers = intArrayOf(10, 20, 30, 40, 50)
val zeros = IntArray(5) { 0 }
val sequence = IntArray(5) { index -> index * 2 }
val bytes = byteArrayOf(1, 2, 3, 4, 5)
val chars = charArrayOf('K', 'o', 't', 'l', 'i', 'n')
val doubles = doubleArrayOf(1.5, 2.7, 3.9, 4.1)
val floats = floatArrayOf(1.0f, 2.0f, 3.0f)
val longs = longArrayOf(100L, 200L, 300L)
val shorts = shortArrayOf(10, 20, 30)
val booleans = booleanArrayOf(true, false, true)
Every Kotlin array has a size property indicating the number of elements:
val cities = arrayOf("New York", "London", "Tokyo", "Paris")
println("Array contains ${cities.size} cities")
// Output: Array contains 4 cities
The indices property returns a range of valid array indices:
val colors = arrayOf("Red", "Green", "Blue", "Yellow")
for (index in colors.indices) {
println("Color at index $index: ${colors[index]}")
}
Access the last valid index directly:
val fruits = arrayOf("Apple", "Banana", "Orange")
println("Last fruit: ${fruits[fruits.lastIndex]}")
// Output: Last fruit: Orange
Kotlin arrays use zero-based indexing for element access:
val languages = arrayOf("Java", "Kotlin", "Python", "JavaScript")
// Reading elements
val firstLanguage = languages[0] // "Java"
val lastLanguage = languages[3] // "JavaScript"
// Modifying elements
languages[1] = "Scala"
println(languages.joinToString()) // Java, Scala, Python, JavaScript
Alternative syntax for accessing array elements:
val numbers = intArrayOf(10, 20, 30, 40)
// Reading with get()
val secondNumber = numbers.get(1) // 20
// Writing with set()
numbers.set(2, 35)
println(numbers.joinToString()) // 10, 20, 35, 40
The most readable way to iterate through Kotlin arrays:
val subjects = arrayOf("Mathematics", "Physics", "Chemistry", "Biology")
for (subject in subjects) {
println("Studying: $subject")
}
When you need both index and value:
val grades = intArrayOf(85, 92, 78, 96, 88)
for (i in grades.indices) {
println("Grade ${i + 1}: ${grades[i]}")
}
Functional approach for array iteration:
val countries = arrayOf("USA", "Canada", "Mexico", "Brazil")
countries.forEach { country ->
println("Country: $country")
}
Access both index and element in functional style:
val programmingLanguages = arrayOf("C++", "Java", "Kotlin", "Python")
programmingLanguages.forEachIndexed { index, language ->
println("Language $index: $language")
}
Transform array elements using the map() function:
val temperatures = doubleArrayOf(20.5, 25.3, 18.7, 22.1)
val fahrenheit = temperatures.map { celsius -> celsius * 9/5 + 32 }
println("Fahrenheit: ${fahrenheit.joinToString()}")
Select elements based on conditions:
val scores = intArrayOf(45, 78, 92, 65, 88, 34, 91)
val passingScores = scores.filter { it >= 60 }
val highScores = scores.filter { it >= 90 }
println("Passing scores: ${passingScores.joinToString()}")
println("High scores: ${highScores.joinToString()}")
Combine array elements into single values:
val expenses = doubleArrayOf(25.50, 45.20, 12.75, 67.30, 33.10)
val totalExpenses = expenses.reduce { acc, expense -> acc + expense }
val averageExpense = expenses.average()
println("Total expenses: $totalExpenses")
println("Average expense: $averageExpense")
Sort arrays according to natural order:
val randomNumbers = intArrayOf(64, 23, 87, 45, 91, 12, 56)
val sortedAscending = randomNumbers.sorted()
val sortedDescending = randomNumbers.sortedDescending()
println("Ascending: ${sortedAscending.joinToString()}")
println("Descending: ${sortedDescending.joinToString()}")
Implement custom sorting logic:
val words = arrayOf("elephant", "cat", "butterfly", "dog", "ant")
val sortedByLength = words.sortedBy { it.length }
val sortedByLastChar = words.sortedBy { it.last() }
println("By length: ${sortedByLength.joinToString()}")
println("By last character: ${sortedByLastChar.joinToString()}")
Modify the original array directly:
val mutableNumbers = intArrayOf(89, 23, 67, 45, 12)
mutableNumbers.sort()
println("Sorted in-place: ${mutableNumbers.joinToString()}")
Check if arrays contain specific elements:
val availableColors = arrayOf("red", "green", "blue", "yellow", "purple")
if ("blue" in availableColors) {
println("Blue is available")
}
val hasRed = availableColors.contains("red")
val hasPink = availableColors.contains("pink")
println("Has red: $hasRed")
println("Has pink: $hasPink")
Locate elements with specific criteria:
val studentAges = intArrayOf(18, 19, 20, 17, 21, 19, 18)
val firstAdult = studentAges.find { it >= 18 }
val lastTeenager = studentAges.findLast { it < 20 }
val adultIndex = studentAges.indexOfFirst { it >= 21 }
println("First adult age: $firstAdult")
println("Last teenager age: $lastTeenager")
println("First adult index: $adultIndex")
Compare array contents using specialized functions:
val firstArray = arrayOf("apple", "banana", "cherry")
val secondArray = arrayOf("apple", "banana", "cherry")
val thirdArray = arrayOf("apple", "cherry", "banana")
val areEqual = firstArray.contentEquals(secondArray)
val areNotEqual = firstArray.contentEquals(thirdArray)
println("First and second arrays equal: $areEqual")
println("First and third arrays equal: $areNotEqual")
For nested arrays, use contentDeepEquals():
val nestedArray1 = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
val nestedArray2 = arrayOf(arrayOf(1, 2), arrayOf(3, 4))
val deepEqual = nestedArray1.contentDeepEquals(nestedArray2)
println("Nested arrays equal: $deepEqual")
Create and work with 2D arrays:
val gameBoard = Array(3) { Array(3) { "-" } }
// Set some values
gameBoard[0][0] = "X"
gameBoard[1][1] = "O"
gameBoard[2][2] = "X"
// Print the board
for (row in gameBoard) {
println(row.joinToString(" | "))
}
For complex data structures:
val cube = Array(3) { Array(3) { Array(3) { 0 } } }
// Fill with sequential numbers
var counter = 1
for (i in cube.indices) {
for (j in cube[i].indices) {
for (k in cube[i][j].indices) {
cube[i][j][k] = counter++
}
}
}
Convert arrays to lists for dynamic operations:
val staticFruits = arrayOf("apple", "banana", "orange", "grape")
val mutableFruitList = staticFruits.toMutableList()
mutableFruitList.add("kiwi")
mutableFruitList.remove("banana")
println("Updated fruits: ${mutableFruitList.joinToString()}")
Remove duplicates by converting to Set:
val duplicateNumbers = intArrayOf(1, 2, 3, 2, 4, 1, 5, 3)
val uniqueNumbers = duplicateNumbers.toSet()
println("Original: ${duplicateNumbers.joinToString()}")
println("Unique: ${uniqueNumbers.joinToString()}")
Convert between primitive and object arrays:
val primitiveArray = intArrayOf(10, 20, 30, 40, 50)
val objectArray = primitiveArray.toTypedArray()
println("Primitive type: ${primitiveArray::class.simpleName}")
println("Object type: ${objectArray::class.simpleName}")
Extract portions of arrays:
val alphabet = arrayOf("A", "B", "C", "D", "E", "F", "G", "H")
val firstHalf = alphabet.sliceArray(0..3)
val lastHalf = alphabet.sliceArray(4..7)
val middlePart = alphabet.sliceArray(2..5)
println("First half: ${firstHalf.joinToString()}")
println("Last half: ${lastHalf.joinToString()}")
println("Middle part: ${middlePart.joinToString()}")
Combine multiple arrays:
val firstNames = arrayOf("John", "Jane", "Bob")
val lastNames = arrayOf("Doe", "Smith", "Johnson")
val combinedNames = firstNames + lastNames
println("Combined: ${combinedNames.joinToString()}")
Split arrays based on conditions:
val allNumbers = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val (evenNumbers, oddNumbers) = allNumbers.partition { it % 2 == 0 }
println("Even numbers: ${evenNumbers.joinToString()}")
println("Odd numbers: ${oddNumbers.joinToString()}")
data class Student(val name: String, val grade: Double)
fun demonstrateGradeSystem() {
val students = arrayOf(
Student("Alice Johnson", 92.5),
Student("Bob Wilson", 87.3),
Student("Carol Davis", 95.8),
Student("David Brown", 84.2),
Student("Emma Miller", 91.7)
)
// Calculate statistics
val averageGrade = students.map { it.grade }.average()
val topStudent = students.maxByOrNull { it.grade }
val passingStudents = students.filter { it.grade >= 85.0 }
println("Class average: $averageGrade")
println("Top student: ${topStudent?.name} with ${topStudent?.grade}")
println("Passing students: ${passingStudents.size}")
// Sort by grade descending
val rankedStudents = students.sortedByDescending { it.grade }
println("\nClass rankings:")
rankedStudents.forEachIndexed { index, student ->
println("${index + 1}. ${student.name}: ${student.grade}")
}
}
data class Product(val id: String, val name: String, val quantity: Int, val price: Double)
fun demonstrateInventorySystem() {
val inventory = arrayOf(
Product("P001", "Laptop Computer", 15, 999.99),
Product("P002", "Wireless Mouse", 50, 29.99),
Product("P003", "Mechanical Keyboard", 25, 149.99),
Product("P004", "USB Cable", 100, 12.99),
Product("P005", "Monitor Stand", 8, 79.99)
)
// Find low stock items
val lowStockItems = inventory.filter { it.quantity < 20 }
// Calculate total inventory value
val totalValue = inventory.sumOf { it.quantity * it.price }
// Find most expensive item
val expensiveItem = inventory.maxByOrNull { it.price }
println("Low stock alerts:")
lowStockItems.forEach { product ->
println("${product.name}: Only ${product.quantity} left")
}
println("\nTotal inventory value: $${String.format("%.2f", totalValue)}")
println("Most expensive item: ${expensiveItem?.name} at $${expensiveItem?.price}")
// Reorder suggestions
val reorderList = inventory.filter { it.quantity < 15 }
println("\nReorder suggestions:")
reorderList.forEach { product ->
val suggestedOrder = 50 - product.quantity
println("${product.name}: Order $suggestedOrder units")
}
}
data class WeatherReading(val day: String, val temperature: Double, val humidity: Int, val rainfall: Double)
fun demonstrateWeatherAnalysis() {
val weeklyWeather = arrayOf(
WeatherReading("Monday", 22.5, 65, 0.0),
WeatherReading("Tuesday", 25.3, 70, 2.5),
WeatherReading("Wednesday", 18.7, 80, 15.2),
WeatherReading("Thursday", 21.9, 68, 0.0),
WeatherReading("Friday", 26.1, 55, 0.0),
WeatherReading("Saturday", 28.4, 45, 0.0),
WeatherReading("Sunday", 24.8, 60, 1.8)
)
// Temperature analysis
val avgTemperature = weeklyWeather.map { it.temperature }.average()
val maxTemp = weeklyWeather.maxByOrNull { it.temperature }
val minTemp = weeklyWeather.minByOrNull { it.temperature }
// Rainfall analysis
val totalRainfall = weeklyWeather.sumOf { it.rainfall }
val rainyDays = weeklyWeather.filter { it.rainfall > 0.0 }
// Humidity analysis
val avgHumidity = weeklyWeather.map { it.humidity }.average()
val highHumidityDays = weeklyWeather.filter { it.humidity > 70 }
println("Weekly Weather Summary:")
println("Average temperature: ${String.format("%.1f", avgTemperature)}°C")
println("Hottest day: ${maxTemp?.day} at ${maxTemp?.temperature}°C")
println("Coldest day: ${minTemp?.day} at ${minTemp?.temperature}°C")
println("Total rainfall: ${totalRainfall}mm")
println("Rainy days: ${rainyDays.size}")
println("Average humidity: ${String.format("%.1f", avgHumidity)}%")
println("\nHigh humidity days:")
highHumidityDays.forEach { reading ->
println("${reading.day}: ${reading.humidity}% humidity")
}
}
Here’s a comprehensive example showcasing various Kotlin array operations:
fun main() {
println("=== Kotlin Arrays Comprehensive Demo ===\n")
// Array creation and initialization
println("1. Array Creation:")
val cities = arrayOf("Tokyo", "New York", "London", "Paris", "Sydney")
val numbers = IntArray(5) { index -> (index + 1) * 10 }
val matrix = Array(3) { Array(3) { 0 } }
println("Cities: ${cities.joinToString()}")
println("Numbers: ${numbers.joinToString()}")
println("Matrix created: ${matrix.size}x${matrix[0].size}")
// Array properties and access
println("\n2. Array Properties:")
println("Cities array size: ${cities.size}")
println("First city: ${cities[0]}")
println("Last city: ${cities[cities.lastIndex]}")
println("Valid indices: ${cities.indices}")
// Array modification
println("\n3. Array Modification:")
val mutableCities = cities.copyOf()
mutableCities[2] = "Berlin"
println("Modified cities: ${mutableCities.joinToString()}")
// Array iteration
println("\n4. Array Iteration:")
print("Iteration with forEach: ")
numbers.forEach { print("$it ") }
println("\nIteration with indices:")
cities.forEachIndexed { index, city ->
println(" [$index] = $city")
}
// Array transformations
println("\n5. Array Transformations:")
val temperatures = doubleArrayOf(20.0, 25.5, 18.3, 22.7, 26.1)
val fahrenheit = temperatures.map { celsius -> celsius * 9/5 + 32 }
val hotDays = temperatures.filter { it > 22.0 }
println("Celsius: ${temperatures.joinToString()}")
println("Fahrenheit: ${fahrenheit.joinToString { String.format("%.1f", it) }}")
println("Hot days (>22°C): ${hotDays.joinToString()}")
// Array sorting and searching
println("\n6. Sorting and Searching:")
val scores = intArrayOf(85, 92, 78, 96, 88, 91, 87)
val sortedScores = scores.sorted()
val topScore = scores.maxOrNull()
val passCount = scores.count { it >= 80 }
println("Original scores: ${scores.joinToString()}")
println("Sorted scores: ${sortedScores.joinToString()}")
println("Top score: $topScore")
println("Passing scores (≥80): $passCount")
// Array comparisons
println("\n7. Array Comparisons:")
val array1 = arrayOf(1, 2, 3, 4, 5)
val array2 = arrayOf(1, 2, 3, 4, 5)
val array3 = intArrayOf(1, 2, 3, 4, 5)
println("Arrays equal (content): ${array1.contentEquals(array2)}")
println("Array to IntArray equal: ${array1.contentEquals(array3.toTypedArray())}")
// Array conversions
println("\n8. Array Conversions:")
val originalArray = arrayOf("apple", "banana", "apple", "cherry", "banana")
val uniqueList = originalArray.toSet().toList()
val mutableList = originalArray.toMutableList()
println("Original: ${originalArray.joinToString()}")
println("Unique items: ${uniqueList.joinToString()}")
mutableList.add("orange")
println("Extended list: ${mutableList.joinToString()}")
// Advanced operations
println("\n9. Advanced Operations:")
val sales = doubleArrayOf(1200.50, 1450.75, 980.25, 1680.90, 1320.60)
val totalSales = sales.sum()
val averageSales = sales.average()
val (highSales, lowSales) = sales.partition { it > 1300.0 }
println("Sales data: ${sales.joinToString { "$%.2f".format(it) }}")
println("Total sales: $%.2f".format(totalSales))
println("Average sales: $%.2f".format(averageSales))
println("High sales days: ${highSales.size}")
println("Low sales days: ${lowSales.size}")
// Demonstrate the practical examples
println("\n=== Practical Examples ===")
demonstrateGradeSystem()
println()
demonstrateInventorySystem()
println()
demonstrateWeatherAnalysis()
}
// Run the complete demonstration
main()
Kotlin arrays provide powerful data management capabilities for developers working on various applications. From basic array declaration using arrayOf() to advanced operations like filtering, mapping, and sorting, Kotlin arrays offer comprehensive functionality for handling collections of data efficiently.
Understanding array properties like size, indices, and lastIndex helps in safe array manipulation, while transformation operations enable complex data processing scenarios. The distinction between primitive arrays (IntArray, DoubleArray) and object arrays (Array<T>) allows for optimized memory usage based on specific requirements.