-
15강. 코틀린에서 배열과 컬렉션을 다루는 방법BackEnd/Kotlin 2024. 3. 21. 05:00반응형
- 배열(Array)
- 컬렉션(Collection) - List, Set, Map
- 컬렉션의 null 가능성
- Java와 함께 사용할 때 주의할 점
배열
배열은 잘 사용하지 않습니다. Effective Java에도 '배열보다 리스트를 사용하라'라고 되어 있습니다.
다음은 배열을 사용한 Java 코드입니다.
int[] array = {100, 200}; for (int i = 0; i < array.length; i++) { System.out.printf("%s %s", i, array[i]); }
Kotlin으로 구현하면 다음과 같습니다.
val array = arrayOf(100, 200) for (i in array.indices) { println("${i} ${array[i]}") } for ((idx, value) in array.withIndex()) { println("$idx $value") }
- array.indices: 0부터 마지막 index까지의 Range입니다.
- withIndex(): index와 value를 한 번에 가져올 수 있습니다.
Collection
컬렉션을 만들어 줄 때 불변인지, 가변인지를 설정해줘야 합니다. 다음은 Kotlin의 Collection 계층 구조입니다.
- 가변 (Mutable) 컬렉션: 컬렉션에 element를 추가, 삭제할 수 있습니다.
- 불변 컬렉션: 컬렉션에 element를 추가, 삭제할 수 없습니다. 단, 불변 컬렉션이라도 Reference Type인 Element의 필드는 바꿀 수 있습니다.
List
다음은 Java의 List 코드입니다.
public static void main(String[] args) { // List final List<Integer> numbers = Arrays.asList(100, 200); // get System.out.println(numbers.get(0)); // For Each for (int number : numbers) { System.out.println(number); } // for문 for (int i = 0; i < numbers.size(); i++) { System.out.printf("%s %s,", i, numbers.get(i)); } }
Kotlin으로 구현하면 다음과 같습니다.
fun main() { // List val numbers = listOf(100, 200) val emptyList = emptyList<Int>() // 비어있는 리스트의 경우 타입을 명시해 주어야 합니다. // get println(numbers.get(0)) println(numbers[0]) // For Each for (number in numbers) { println(number) } // 전통적인 for문 for ((index, number) in numbers.withIndex()) { println("$index $number") } }
emptyList의 경우, 타입을 추론할 수 있다면 생략 가능합니다.
fun main() { printNumbers(emptyList()) } private fun printNumbers(numbers: List<Int>) { }
가변 리스트를 만들고 싶다면, listOf() 대신 mutableList()를 사용하면 됩니다.
val mutableNumbers = mutableListOf(100, 200) mutableNumbers.add(300)
- add, remove, addAll, removeAll 같은 Java에 존재하는 모든 라이브러리 기능들이 Kotlin에도 존재합니다.
- 기본 구현체는 ArrayList이고, 기타 사용법은 Java와 동일합니다.
Note. 우선 불변 리스트를 만들고, 반드시 필요한 경우에만 가변 리스트로 바꾸어 사용합니다.
Set
집합은 List와 다르게 순서가 없고, 같은 element는 하나만 존재할 수 있습니다. 자료구조적 의미만 제외하면 모든 기능이 List와 비슷합니다.
다음은 Kotlin 코드입니다.
// Set val setNumbers = setOf(100, 200) // For Each for (number in setNumbers) { println(number) } // 전통적인 for문 for ((index, number) in numbers.withIndex()) { println("$index $number") }
가변(Mutable) 집합을 만들고 싶다면, mutableSetOf()를 사용하시면 됩니다.
val setNumbers = mutableSetOf(100, 200)
- 기본 구현체는 LinkedHashSet 입니다.
Map
다음은 Map을 생성하는 Java 코드입니다.
// JDK 8까지 Map<Integer, String> map = new HashMap<>(); map.put(1, "MONDAY"); map.put(2, "TUESDAY"); // JDK 9부터 Map.of(1, "MONDAY", 2, "TUESDAY");
Kotlin으로 구현하면 다음과 같습니다.
val oldMap = mutableMapOf<Int, String>() oldMap.put(1, "MONDAY") oldMap[2] = "TUESDAY" mapOf(1 to "MONDAY", 2 to "TUESDAY")
- 가변 Map이기 때문에 (key, value)를 넣을 수 있습니다.
- Java처럼 put을 쓸 수도 있고, map[key] = value을 쓸 수도 있습니다.
- mapOf(key to value)를 사용해 불변 map을 만들 수 있습니다.
다음은 Java에서 Map을 활용하는 코드입니다.
for (int key : map.keySet()) { System.out.println(key); System.out.println(map.get(key)); } for (Map.Entry<Integer, String> entry : map.entrySet()) { System.out.println(entry.getKey()); System.out.println(entry.getValue()); }
Kotlin으로 구현하면 다음과 같습니다.
for (key in oldMap.keys) { println(key) println(oldMap[key]) } for ((key, value) in oldMap.entries) { println(key) println(value) }
컬렉션의 null 가능성
- List<Int?>: List에 null이 들어갈 수 있지만, List는 절대 null이 아닙니다.
- List<Int>?: List에는 null이 들어갈 수 없지만, List는 null일 수 있습니다.
- List<Int?>?: List에 null이 들어갈 수도 있고, List가 null일 수도 있습니다.
? 위치에 따라 null 가능성 의미가 달라지므로 차이를 잘 이해해야 합니다.
Java와 함께 사용할 때 주의할 점
- Java는 읽기 전용 컬렉션과 변경 가능 컬렉션을 구분하지 않습니다.
- Java는 nullable 타입과 non-nullable 타입을 구분하지 않습니다.
- Kotlin 쪽의 컬렉션이 Java에서 호출되면 컬렉션 내용이 변할 수 있음을 감안해야 합니다.
- Kotlin 쪽에서 Collections.unmodifableXXX()를 활용하면 변경 자체를 막을 수는 있습니다.
- Kotlin에서 Java 컬렉션을 가져다 사용할 때는 플랫폼 타입을 신경써야 합니다. Java 코드를 보며 맥락을 확인하고, Java 코드를 가져오는 지점을 wrapping해서 영향 범위를 최소화하는 것이 좋습니다.
감사합니다.
반응형'BackEnd > Kotlin' 카테고리의 다른 글
17강. 코틀린에서 람다를 다루는 방법 (1) 2024.04.07 16강. 코틀린에서 다양한 함수를 다루는 방법 (0) 2024.04.06 14강. 코틀린에서 다양한 클래스를 다루는 방법 (0) 2024.03.13 13강. 코틀린에서 중첩 클래스를 다루는 방법 (0) 2024.03.08 12강. 코틀린에서 object 키워드를 다루는 방법 (0) 2024.03.07