-
kotlin) 코틀린에서의 FPkotlin 2024. 7. 9. 23:04
코틀린에서 배열과 컬렉션을 다루는 방법
1. 배열
//Java int[] array= {100, 200}; for(int i = 0; i < array.length; i++) { System.out.println(array[i]); } //Kotlin val array = arrayOf(100,200) array.plus(300) //값을 쉽게 넣을 수 있다. //1. array.indices : Index 만 가져옴 for(i in array.indices) { println(array[i]) } //2. withIndex : Index 와 value 를 한번에 받음 for((idx, value) in array.withIndex()) { println(idx) println(value) }
2. 코틀린에서의 Collection - List, Set, Map
컬렉션을 만들어줄 때 불변인지, 가변인지를 설정해야 한다.
가변 컬렉션 : 컬렉션에 element 를 추가 삭제할 수 있다.
불변 컬렉션 : 컬렉션에 element 를 추가 삭제할 수 없다.
* element : 콜렉션 내부에 저장되는 각각의 개별 항목
코틀린에서 람다를 다루는 방법
1. Java에서 람다를 다루기 위한 노력
기존 Java 의 문제점
- '익명 클래스' 를 사용하는것은 복잡하다.
- 다양한 Filter 가 필요할 수 있다.
-> JDK8 부터 람다 (이름이 없는 함수) 등장
람다
- 변수 -> 변수를 이용한 함수
- (변수1, 변수2) -> 변수1과 변수 2를 이용한 함수
- 간결한 스트림 등장
기존 Java 에서 함수 특징
- 메소드 자체를 직접 넘겨주는 것처럼 쓸 수 있다.
- Java 에서는 함수는 변수에 할당되거나 파라미터로 전달할 수 없다.
2. 코틀린에서의 람다
Java 와 다른 Kotlin 만의 특징 : 코틀린에서는 함수가 그 자체로 값이 될 수 있다. 변수에 할당할수도, 파라미터로 넘길 수도 있다.
fun main() { var fruits = listOf( Fruit("사과", 1000), Fruit("사과", 1200), Fruit("사과", 1200), Fruit("사과", 1500), Fruit("바나나", 3000), Fruit("바나나", 3200), Fruit("바나나", 2500), Fruit("수박", 10000) ) //원래 fun 함수이름(fruit: Fruit) 이 되어야하지만 이름이 없기에 이름없는 함수(람다) 가 된다. var isApple = fun(fruit: Fruit): Boolean { return fruit.name == "사과" } var isApple2 = {fruit: Fruit -> fruit.name == "사과"} isApple(fruits[0]) isApple.invoke(fruits[0]) }
//Java private List<Fruit> filterFruits(List<Fruit> fruits, Predicate<Fruit> fruitFilter) { List<Fruit> results = new ArrayList<>(); for (Fruit fruit : fruits) { if (fruitFilter.test(fruit)) { results.add(fruit); } } return results; } fun main() { var fruits = listOf( Fruit("사과", 1000), Fruit("사과", 1200), Fruit("사과", 1200), Fruit("사과", 1500), Fruit("바나나", 3000), Fruit("바나나", 3200), Fruit("바나나", 2500), Fruit("수박", 10000) ) //원래 fun 함수이름(fruit: Fruit) 이 되어야하지만 이름이 없기에 이름없는 함수(람다) 가 된다. var isApple = fun(fruit: Fruit): Boolean { return fruit.name == "사과" } var isApple2 = {fruit: Fruit -> fruit.name == "사과"} filterFruits(fruits, isApple) //직접적으로 함수 사용 가능 filterFruits(fruits, isApple2) filterFruits(fruits, {fruit: Fruit -> fruit.name == "사과" }) filterFruits(fruits) {it.name == "사과"} //극단적으로 생략이 가능하다, it은 파라미터가 1개일 경우 사용 가능하다. } //Kotlin private fun filterFruits(fruits: List<Fruit>, filter: (Fruit) -> Boolean): List<Fruit> { val results = mutableListOf<Fruit>() for (fruit in fruits) { if (filter(fruit)) { results.add(fruit) } } return results }
함수의 인터페이스를 쓰는게 아니라 함수 자체를 파라미터로 받아서 사용할 수 있다.
3. Closure
코틀린에서는 람다가 시작하는 시점에 참조하고 있는 변수들을 모두 포획하여 그 정보를 가지고 있다.
//Java String targetFruitName = "바나나"; targetFruitName = "수박"; //Java 에서는 람다를 쓸 때 사용할 수 있는 변수에 제약이 있다. filterFruits(fruits, (fruit -> targetFruitName.equals(fruit.getName()))); //에러 발생 //Kotlin var targetFruitName = "바나나" targetFruitName = "수박" //Kotlin 에서는 문제없이 돌아간다. filterFruits(fruits) {it.name == targetFruitName}
이렇게 해야만, 람다를 진정한 일급 시민으로 간주할 수 있다.
이 데이터 구조를 Closure 라고 한다.
코틀린에서 컬렉션을 함수형으로 다루는 방법
1. 필터와 맵
fun main() { var fruits = listOf( Fruit("사과", 1000), Fruit("사과", 1200), Fruit("사과", 1200), Fruit("사과", 1500), Fruit("바나나", 3000), Fruit("바나나", 3200), Fruit("바나나", 2500), Fruit("수박", 10000) ) //사과만 주세요 //방법 1 : 단순 검색 val apples1 = fruits.filter { fruit -> fruit.name == "사과"} //방법 2 : 인덱스까지 val apples2 = fruits.filterIndexed{ index, fruit -> println(index) fruit.name == "사과" } //Map 을 통한 가격 검색 //방법 1 : 사과 중에서 가격 val applePrices1 = fruits.filter {fruit -> fruit.name == "사과" } .map {fruit -> fruit.price} //방법 2 : 인덱스 까지 val applePrices2 = fruits.filter {fruit -> fruit.name == "사과" } .mapIndexed { index, fruit -> println(index) fruit.price } //방법 3 : null 제외 val applePriceNotNull = fruits.filter {fruit -> fruit.name == "사과" } .mapNotNull { fruit -> fruit.price } }
2. 다양한 컬렉션 처리 기능
//all : 조건을 모두 만족하면 true 그렇지 않으면 false val isAllApple = fruits.all {fruit -> fruit.name == "사과"} //none : 조건을 모두 불만족하면 true 그렇지 않으면 false val isNoApple = fruits.none {fruit -> fruit.name == "사과"} //any : 조건을 하나라도 만족하면 true 그렇지 않으면 false val isAnyApple = fruits.any{fruit -> fruit.price >= 10000}
3. List 를 Map 으로
//과일 이름이 Key 이고 이름을 토대로 Map 을 만들고싶을때 val fruitNameMap : Map<String, List<Fruit>> = fruits.groupBy { fruit -> fruit.name } val fruitIdMap : Map<Long, Fruit> = fruits.associate { fruit -> fruit.id } //List<List<Fruit>> 를 List<Fruit> 로 바꿀때 fruiltInList.fatten()
'kotlin' 카테고리의 다른 글
kotlin) Kotlin 의 지연과 위임 (0) 2024.07.18 kotlin) 추가적으로 알아두어야 할 코틀린 특성 (0) 2024.07.13 kotlin) 코틀린에서의 OOP (0) 2024.07.06 kotlin) 코틀린에서 변수와 타입, 연산자를 다루는 방법 (0) 2024.07.04 kotlin) 코틀린에서 코드를 제어하는 방법 (0) 2024.07.02