제네릭 함수 혹은 메서드
fun <형식 매개변수[,...]> 함수 이름(매개변수: <매개변수 자료형>[, ...]): <반환 자료형>
예)
fun <T> genericFunc(arg: T): T? {...} // 매개변수와 반환 자료형에 형식 매개변수 T가 사용됨
fun <K, V> put(key: K, value: V): Unit {...} // 형식 매개변수가 2개인 경우
배열의 인덱스 찾아내기
제네릭과 람다식
람다식에서 제네릭 사용
자료형 제한하기
자바에서 extends나 super를 사용해 제한한것을 코틀린에서는 콜론(:)을 사용해 제한한다.
클래스에서 형식 매개변수의 자료형 제한하기
자료형을 숫자형으로 제한하기
함수에서 형식 매개변수의 자료형 제한하기
다수 조건의 형식 매개변수 제한하기
2개의 특정 인터페이스 구현이 포함된 클래스로 형식 매개변수를 제한하려고 할때 -> where
키워드를 사용해 지정된 제한을 모두 포함하는 경우에만 허용하도록 할 수 있다.
가변성의 3가지 유형
배열 선언 및 접근 연습하기
다차원 배열을 전부 출력하고 싶을때는 Arrays.deepToString(array)
를 사용하면 전체 출력해준다.
표현식을 통해 배열 생성하기
val|var 변수 이름 = Array(요소 개수, 초깃값)
ex)
val arr3 = Array(5, {i -> i * 2 }) // 0,2,4,6,8
var a = arrayofNulls <Int>(1000) // 1000개 null로 채우기
var a = Array(1000, { 0 }) // 0으로 채워진 배열
var a = Array(1000, { i -> msClass(i) })
val arr2 = arr1.plus(6)
val arr3 = arr1.sliceArray(0..2) // 필요한 범위를 잘라내 새 배열 생성 / 0,1,2번째만 잘라서 만들어진다.
arr.first() // 첫번재 요소 확인
arr.last() // 마지막 요소 확인
arr.indexOf(3) // 요소 3의 인덱스 출력
arr.average() // 배열의 평균 값 출력
arr.count() // 요소 개수 세기
arr.contains(4) // arr 배열에 요소 4가 포함되었는지 확인
arr.forEach { element -> print("$element")}
arr.forEachIndexed({ i, e -> println("arr[$i] = $e") {)
iterator()를 사용해 요소 순환을 할 수 있다.
val iter: Iterator<Int> = arr.iterator()
while (iter.hasNext()) {
val e = iter.next()
print("$e ")
}
기본적인 정렬 방법
sortWith() 비교자로 정렬
주어진 비교자(Comparator)에 의해 정렬
Comparator를 사용해 제품 비교하기
배열 필터링하기
filter()
메서드를 활용하면 원하는 데이터를 골라낼 수 있다.
필요한 정보만 골라내어 변경하기
filter로 요소를 골라내 map으로 받아 대문자로 변경하고 출력
가장 작은 값과 큰 값 골라내기
.minBy
.maxBy
배열 평탄화하기
flatten()
매서드
substring(인덱스 범위 지정)
s1.compareTo(s2)
: 같으면 0, s1이 s2보다 작으면 양수, 그렇지 않으면 음수 반환, s1.comparTo(s2, true))
는 대소문자 무시StringBuilder("Hello")
와 같이 StringBuilder를 사용. 나중에 값을 변경할때 새로운 공간에 만들어지지 않고 원래 저장공간에 할당된 것을 바꾼다.이외에 여러 문자열 관련 함수존재'
서점 예제 작성하기
컬렉션 | 불변형(읽기 전용) | 가변형 |
---|---|---|
List | listOf | mutableListOf, arrayListOf |
Set | setOf | mutableSetOf, hashSetOf, linkedSetOf, sortedSetOf |
Map | mapOf | mutableMapOf, hashMapOf, linkedMapOf, sortedMapOf |
순서에 따라 정렬된 요소를 가지는 컬렉션
불변형과 가변형이 있다는 것을 생각하고 헬퍼함수를 만든다.
List와 배열의 차이
Set은 정해진 순서가 없는 요소들의 집합을 나타내는 컬렉션.
Map은 요소가 키와 값의 쌍 형태로 저장된다. 키는 중복될수 없고 유일하다.
hashSetOf과 hashMapOf은 해시테이블에 요소를 저장할 수 있다. 해시 테이블이란 내부적으로 키와 인덱스를 이용해 검색과 변경 등을 매우 빠르게 처리할수 있는 자료구조이다.
sortedSetOf와 sortedMapOf는 자바의 TreeSet 컬렉션을 정렬된 상태로 반환한다. 트리셋은 저장된 데이터의 값에 따라 정렬되는데, 일종의 개선된 이진 탐색 트리인 레드 블랙 트리 알고리즘을 사용해 자료구조를 구성한다. 최악으로 요소 배치가 되어도 검색등의 처리에서 일정한 시간을 보장하는 자료구조이다. HashSet보다 성능이 좀 떨어지고 데이터를 추가하거나 삭제하는데 시간이 걸리지만 검색과 정렬이 뛰어나다는 장점이 있다.
linkedSetOf와 linkedMapOf는 자바의 LinkedHashSet 자료형을 반환하는 헬퍼 함수이다. 링크드 리스트를 사용해 구현된 해시 테이블에 요소를 저장한다. 저장된 순서에 따라 값이 정렬되며 hash, tree보다 느리다. 다만 자료구조상 다음 데이터를 가리키는 포인터 연결을 통해 메모리 저장 공간을 좀더 효율적으로 사용할 수 있다.
코틀린의 시퀸스(Sequence)는 순차적인 컬렉션으로 요소의 크기를 특정하지 않고, 나중에 결정할 수 있는 특수한 컬렉션이다. 시퀸스는 처리 중에는 계산하고 있지 않다가 toList()나 count()같은 최종 연산에 의해 결정된다.
요소 값 생성하기
generateSequence()
로 생성하기
시퀸스 사용하기
시드인수에 의해 시작 요소의 값이 결정된다.
주어진 식에 따라 새로운 컬렉션을 반환하는 amp이나 filter같은 연산을 사용할 수도 있다.
요소 값 가져오기
asSequence()사용하기
시퀸스를 이용한 피보나치 수열 출력하기
val 변수 이름: 자료형 선언 = { 매개변수[,...] -> 람다식 본문 }
val sum: (Int, Int) -> Int = { x,y -> x + y }
val mul = {x: Int, y: Int -> x*y }
val add: (Int) -> Int = {it + 1}
val isPositive: (Int) -> Boolean = {
val isPositive = it > 0
isPositive // 마지막 표현식이 반환됨
}
val isPositiveLabel: (Int) -> Boolean = number@ {
val isPositive = it > 0
return@number isPositive // 라벨을 사용해 반환됨
고차함수는 함수의 매개변수로 함수를 받거나 함수 자체를 반환할 수 잇는 함수이다.
fun inc(x: Int): Int {
return x + 1
}
fun high(name: String, body: (Int)->Int): Int {
println("name: $name")
val x = 0
return body(x)
위처럼 high 의 두번째 매개변수 body는 람다식 함수를 받을 수 있다. 이것을 다시 함수 본문에서 함수로 반환하고 있다.
고차함수 표현법
val result = high("Sean", { x -> inc(x + 3) }) // 함수를 이용한 람다식
val result2 = high("Sean") { inc(it + 3) } // 소괄호 바깥으로 빼내고 생략
val result3 = high("Kim", ::inc) // 매개변수 없이 함수의 이름만 사용할 때
val result4 = high("Sean") { x -> x + 3 } // 람다식 자체를 넘겨준 형태
val result5 = high("Sean") { it + 3 } // 매개변수가 1개인 경우 생략
기본적으로 함수 안에 정의된 변수는 지역 변수로 스택에 저장되어 있다가 함수가 끝나면 같이 사라진다. 하지만 클로저 개념에서는 포획한 변수는 참조가 유지되어 함수가 종료되어도 사라지지 않고 함수의 변수에 접근하거나 수정할 수 잇게 해준다.
클로저의 조건
1. final 변수를 포획한 경우 변수 값을 람다식과 함께 저장한다.
2. final이 아닌 변수를 포획한 경우 변수를 특정 래퍼로 감싸서 나중에 변경하거나 읽을 수 있게 한다. 이 때 래퍼에 대한 참조를 람다식과 함께 저장한다.
클로저 테스트하기
이렇게 클로저를 사용하면 내부의 람다식에서 외부 함수의 변수에 접근해 처리할 수 잇어 효율성이 높다. 또 완전히 다른 함수에서 변수에 접근하는 것을 제한할 수 있다. 코틀린 표준 라이브러리는 이러한 개념이 사용되어 설계되었다.
let()
apply()
with()
also()
run()
등 여러 가지 표준 함수가 있다.
확장 함수의 람다식 접근 방법
함수 이름 | 람다식의 접근 방법 | 반환 방법 |
---|---|---|
T.let | it | block 결과 |
T.also | it | T caller (it) |
T.apply | this | T caller (this) |
T.run 또는 run | this | block 결과 |
with | this | Unit |
Java와 비슷하지만 use()를 사용하면 자동으로 close()를 해준다.
다중 작업을 진행할때 코틀린에서는 코루틴(Coroutine)을 서드파티가 아닌 기본적으로 제공해주고 있다.