Kotlin is a very powerful statically-typed programming language allowing us to write very expressive yet concise code. As is common with modern languages, such expressiveness often means we can implement the same feature in several ways. A typical example is choosing a suitable collection class for our needs.
As a matter of fact, the Kotlin library comes with a variety of different collections, that is, types grouping a number (possibly zero) of collection items.
In this article, we’ll examine arrays and integers in Kotlin. We’ll analyze two different types representing an array of integers, IntArray
and Array
. Finally, we’ll compare IntArray
and Array with
lists, a different collection type.
Jump ahead:
IntArray
vs. Array
Koltin has two different array implementations.
The first is the Array
class, generic over the type T
, representing an array of elements of type T
. Array
defines several methods allowing us to read/write an element at a given index, query the size, and so on. These array implementations are invariant. Hence, Array
is not considered a sub-type of Array
if T
is a subtype of U
.
For primitive types, Kotlin also provides us with dedicated arrays, such as IntArray
or ShortArray
. There’s no subtyping between these “primitive” arrays and their generic counterpart, i.e., Array
. Nonetheless, they come with the same methods.
The main difference between an IntArray
and an Array
is that the former is represented, under the hood, as an int[]
, whereas the latter gets compiled into an Integer[]
.
Type vs. class
The actual difference between IntArray
and an Array
in Kotlin is basically the same as the difference between int
and Integer
in Java. The former is a primitive type, not a class, storing an actual binary value representing a given integer. The latter is a Java class, defining a field of type int
.
Being a class, Integer
is more expressive, as we can invoke methods on it. Nonetheless, int
comes with better performance, as using Integer
adds overhead for even the simplest calculation.
Performance
IntArray
behaves better than Array
in performance-critical situations. According to ”Item 55” of Kotlin Academy’s Effective Kotlin, the latter allocates five times more bytes than the former. Specifically, to store a million numbers, IntArray
requires 4,000,016 bytes, whereas Array
allocates 20,000,040 bytes.
Processing a primitive array is also faster. Again, according to “Item 55” of Effective Kotlin, calculating the average of a million integers is 25% faster with IntArray
.
Initialization
Another difference between IntArray
and. Array
is that primitive arrays can be left uninitialized. More specifically, the elements of the array will be set, by default, to 0
:
val intArr = IntArray(5) println(intArr.joinToString(" "))
The example above will print 0 0 0 0 0
.
On the other hand, we do not have this convenience initialization for Array
. As a matter of fact, its constructor inputs two arguments, one for the size and one for a valid, non-null default value:
val arrInt = Array<Int>(5) { 1 } println(arrInt.joinToString(" "))
The above example will print 1 1 1 1 1
.
We can also use null
values, but the type of the resulting array will be different — and we’ll have to watch out for nulls
:
val arrInt = arrayOfNulls<Int>(5) // Array<Int?> println(arrInt.joinToString(" "))
The above snippet will print null null null null null
, but the type of the array is now Array<Int?>
, rather than Array
.
Creation
Kotlin also provides us with factory functions to create both types of arrays:
val intArray: IntArray = intArrayOf(0, 1, 2, 3) val arrayInt: Array<Int> = arrayOf<Int>(0, 1, 2, 3)
Conversion
We can turn an IntArray
into an Array
, and vice versa, using IntArray::toTypedArray()
and Array::toIntArray()
, respectively:
val arrayInt: Array<Int> = intArrayOf(0, 1, 2, 3).toTypedArray() val intArray: IntArray = arrayOf<Int>(0, 1, 2, 3).toIntArray()
As a final note, the size of both IntArray
and Array
is fixed. Once we set the number of elements, we cannot add or remove items from the arrays.
emptyList()
In addition to arrays, Kotlin provides us with other types of collections. One example is List
. There are several differences between lists and arrays in Kotlin. Here are the main differences:
- Class vs. list:
Array
is a class, whereasList
andMutableList
are interfaces with different implementations. Arrays are sequential fixed-size memory regions, compiled into JVM arrays. However, for lists, it entirely depends on the actual implementation. For instance,ArrayList
makes use of an array under the hood, and hence its runtime performance is similar to that ofArray
- Sizing:
MutableList
is resizable, whereasArray
andList
are not - Mutability:
Array
is mutable, whereasList
is not. If we want to modify the elements of a list, we must useMutableList
- Invariance vs. covariance:
Array
andMutableList are
invariant onT
, whereasList
is covariant. This means thatList
is a subtype ofList
ifT
is a subtype ofU
- Types: Both
Array
andMutableList
are optimized array types for primitive types
We can initialize an empty list using the emptyList()
method and then turn it into an instance of Array
with List::toTypedArray()
, as we did for IntArray
:
val list: List<Int> = emptyList() val array: Array<Int> = list.toTypedArray()
Using arrays in Kotlin
Let’s take a look at the main functions to see how they work on arrays in Kotlin. In the examples that follow, the presented methods apply to both IntArray
and Array
.
Getting and setting elements
The most common operations when working with arrays are surely getting and setting elements. We can do this with the get
and set
methods. Such methods are so commonly invoked that Kotlin defines syntactic sugar for them:
val array = intArrayOf(1, 12, 856, 0, -10) println(array[2]) // same as array.get(2) array[2] = 78 // same as array.set(2, 78) println(array[2])
The example above will print 856
and then 78
, confirming the array was modified in place.
However, if the array is not defined at a given index, Kotlin will throw an IndexOutOfBoundsException
:
val array = intArrayOf(1, 12, 856, 0, -10) println(array[7])
The example above will fail with the following exception: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 5
Traversing an array
We can move through an array in Kotlin using a for
loop or a while
loop. These approaches, however, are a bit low level. Alternatively, Kotlin provides us with the common forEach
function, which is much more declarative than a loop:
val array = intArrayOf(1, 12, 856, 0, -10) array.forEach{ println(it) }
The example above will print all the elements of our array, one for each line.
Sometimes it may be useful to let Kotlin assign indexes to the array’s elements while iterating through the array. We can do that with forEachIndexed
:
val array = intArrayOf(1, 12, 856, 0, -10) array.forEachIndexed{ index, elem -> println("Element at index $index: $elem") }
The example above will print the following output:
Element at index 0: 1 Element at index 1: 12 Element at index 2: 856 Element at index 3: 0 Element at index 4: -10
We can traverse an array using fold
as well. We usually do that when we want to compute a value out of our array. We might use it, for example, to sum all the elements of an array:
val array = intArrayOf(1, 12, 856, 0, -10) val sum = array.fold(0, { acc, elem -> acc + elem }) println(sum)
When using fold
, the first parameter is the initial value of our computation, 0
in the example above. The second argument is a binary function used to update the partial result with each element of the array. The first parameter of such a function is the so-called accumulator, whereas the second is an element of the array. The example above will print 859
, as expected.
Sorting and reversing an array
Sorting and reversing an array are in-place operations. This means that they won’t return a new array, but instead mutate the existing one.
To sort an array we can invoke its sort
method:
val array = arrayOf(1, 12, 856, 0, -10) array.sort() println(array.joinToString(" "))
The example above will print -10 0 1 12 856
, showing that the array was modified. As a matter of fact, the sort
methods return Unit
.
Similarly, to reverse an array we can use reverse
:
val array = arrayOf(1, 12, 856, 0, -10) array.reverse() println(array.joinToString(" "))
The example above will print -10 0 856 12 1
, showing that the array was reversed in place. The reversal can also be partial; that is, we can specify a start and an end:
val array = arrayOf(1, 12, 856, 0, -10) array.reverse(1, 3) println(array.joinToString(" "))
In this case, the example will print 1 856 12 0 -10
, where the elements of the indexes 1
(inclusive) to 3
(exclusive), that is the second and third elements, were reversed.
Conclusion
In this article, we investigated the difference between IntArray
and Array
, comparing different ways of creating instances of each type. We discussed different use cases for both types of arrays, compared them to lists, and saw how to turn a list into an array.
Lastly, we explored some of the most common operations on arrays, in particular how to set or get elements and how to traverse, sort, and reverse an array.
The post Kotlin <code>IntArray</code>, <code>Array</code>, and <code>emptyList()</code> appeared first on LogRocket Blog.
from LogRocket Blog https://ift.tt/HPQNblD
Gain $200 in a week
via Read more