티스토리 뷰
스트림 함수
컬렉션에 포함된 자료의 타입 변경 또는 새로운 자료 추가 생성을 쉽게 구현하기 위해 제공되는 함수
변환
- map() : 컬렉션 내 인자를 함수에 정의된 규칙에 따라 다른 값 혹은 타입으로 변환할 때 사용
val cities = listOf("Seoul", "Tokyo", "Mountain View")
//도시 이름을 대문자로 변환
//출력 결과 : SEOUL TOKYO MOUNTAIN VIEW
cities.map{ city -> city.toUpperCase() }
.forEach{ println(it) }
//도시 이름을 받아, 원소를 각 도시 이름의 문자열 길이로 변환
//출력 결과 : length=5 length=5 length=13
cities.map{ city -> city.length }
.forEach{ println("length=$it") }
- mapIndexed() : 컬렉션 내 포함된 인자의 인덱스 값을 변환 함수 내에서 사용 가능
- mapNotNull() : 컬렉션 내 각 인자를 변환함과 동시에, 결과가 널 값인 경우 이를 원소에서 무시
- flatMap() : map() 함수와 동일하나 하나의 인자에서 여러개의 인자로 매핑 가능
- groupBy() : 컬렉션 내 인자들을 지정한 기준에 따라 분류하며, 각 인자들의 리스트를 포함하는 맵 형태로 결과 반환
필터
- filter() : 컬렉션 내 인자들 중 주어진 조건과 일치하는 인자만 걸러주는 함수
val cities = listOf("Seoul", "Tokyo", "Mountain View")
//도시 이름의 길이가 5 이하인 항목만 통과
//출력 결과 : Seoul Tokyo
cities.filter { city -> city.length <=5 }
.forEach { println(it) }
- take() : 컬렉션 내 인자들 중 take() 함수의 인자로 받은 개수만큼만을 원소로 갖는 리스트 반환
- takeLast() : 뒤에서부터 이 함수의 인자로 받은 개수만큼을 원소로 갖는 리스트 반환
- takeWhile() : 첫번째 인자부터 시작하여 주어진 조건을 만족하는 항목까지를 포함하는 리스트 반환
- takeLastWhile() : 뒤에서부터 주어진 조건을 만족하는 항목까지를 포함하는 리스트 반환
- drop() : take() 함수와 반대, 컬렉션 내 인자들 중 조건을 만족하는 항목를 제외한 리스트 반환
- dropLast() : 뒤에서부터 함수의 인자로 받은 개수만큼을 제외한 리스트 반환
- dropWhile() : 첫번째 인자부터 시작하여 주어진 조건에 해당하는 항목을 제외한 리스트 반환
- dropLastWhile() : 뒤에서부터 주어진 조건을 만족하는 항목까지를 제외한 리스트 반홤
val cities = listOf("Seoul", "Tokyo", "Mountain View", "NYC", "Singapore")
//첫번째 인자로부터 하나의 인자만 포함하는 리스트를 출력
//출력 결과 : Seoul
cities.take(1)
.forEach { println(it) }
//첫번째 인자로부터 하나의 인자를 제외한 리스트 출력
//출력 결과 : Tokyo Mountain View NYC Singapore
cities.drop(1)
.forEach { println(it) }
//문자열의 길이가 5 이하인 조건을 만족할 때까지 해당하는 항목을 제외한 리스트 출력
//출력 결과 : Mountain View NYC Singapore
cities.dropWhile { city -> city.lenth <= 5 }
.forEach { println(it) }
- first() : 첫번째 인자 또는 특정 조건을 만족하는 첫번째 인자 반환, 조건을 만족하지 않으면 NoSuchElementException 예외 발생
- last() : 마지막 인자 또는 특정 조건을 만족하는 마지막 인자 반환, 조건을 만족하지 않으면 NoSuchElementException 예외 발생
val cities = listOf("Seoul", "Tokyo", "Mountain View", "NYC", "Singapore")
//문자열 길이가 5 이상인 첫 번째 인자 반환
//출력 결과 : Mountain View
println.first { city -> city.length > 5 }
//문자열 길이가 5 이하인 마지막 인자 반환
//출력 결과 : NYC
println.last { city -> city.length < 5 }
- distinct() : 중복된 항목을 걸러낸 결과를 반환, 중복 여부는 equals()로 판단
- distinctBy() : 중복된 항목을 판단하는 기준을 직접 설정 가능
val cities = listOf("Seoul", "Tokyo", "Mountain View", "Seoul", "Singapore")
//도시 목록 중 중복된 항목 제거
//출력 결과 : Seoul Tokyo Mountain View Singapore
cities.distinct()
.forEach { println(it) }
//중복된 항목을 판단할 때, 도시 이름의 길이를 판단 기준으로 사용
//출력 결과 : Seoul Mountain View Singapore
cities.distinct { city -> city.length }
.forEach { println{it} }
조합 및 합계
- zip() : 두 컬렉션 내의 자료들을 조합하여 새로운 자료를 만들 때 사용, 기본값으로는 Pair로 결과를 만드며 조합 규칙 지정 가능
val cityCodes = listOf("SEO", "TOK", "MTV", "NYC")
val cityNames = listOf("Seoul", "Tokyo", "Mountain View")
//단순히 zip 함수를 호출하는 경우, Pair 형태로 자료 조합
//출력 결과 : SEO:Seoul TOK:Tokyo MTV:Mountain View
cityCodes.zip(cityNames)
.forEach { pair -> println("${pair.first}:${pair.second}") }
//조합할 자료의 타입을 조합 함수를 통해 지정하면 해당 형태로 변환
//출력 결과 : SEO (Seoul) TOK (Tokyo) MTV (Mountain View)
cityCodes.zip(cityNames) { code, name -> "$code (#name)" }
.forEach { println(it) }
- joinToString() : 컬렉션 내 자료를 문자열 형태로 변환한 후 이를 조합하여 하나의 문자열로 생성, 인자 설정 가능
val cities = listOf("Seoul", "Tokyo", "Mountain View")
//출력 결과 : Seoul, Tokyo, Mountain View
println(cities.joinToString())
//출력 결과 : Seoul|Tokyo|Mountain View
println(cities.joinToString(seperator = "|"))
- count() : 컬렉션 내 포함된 자료의 개수 반환, 조건식 추가 가능
val cities = listOf("Seoul", "Tokyo", "Mountain View", "NYC", "Singapore")
//컬렉션의 모든 자료의 개수 반환
//출력 결과 : 5
println(cities.count())
//컬렉션 내 자료 중, 길이가 5 이하인 자료의 개수 반환
//출력 결과 : 3
println(cities.count { city -> city.length <= 5 })
기타
- any() : 컬렉션 내 자료가 한개라도 존재하는지 여부를 Boolean으로 반환, 조건 추가시 조건식을 만족하는 자료의 유무 여부 반환
- none() : 컬렉션이 비어있는지 여부를 Boolean으로 반환, 조건 추가시 조건식을 만족하는 자료의 유무 여부를 any()와 반대로 반환
val cities = listOf("Seoul", "Tokyo", "Mountain View", "NYC", "Singapore")
//문자열 길이가 5 이하인 자료가 있는지 확인
//출력 결과 : true
print(cities.any { city -> city.length <= 5 })
//빈 문자열을 가진 자료가 없으면 true, 있으면 false 반환
//출력 결과 : true
print(cities.none { city -> city.isEmpty() })
- max() : 숫자 타입의 컬렉션 내 최댓값 반환
- min() : 숫자 타입의 컬렉션 내 최솟값 반환
- average() : 숫자 타입의 컬렉션 내 평균값 반환
val numbers = listOf(4, 2, 5, 3, 2, 0, 8)
//출력 결과 : 8
println(numbers.max())
//출력 결과 : 0
println(numbers.min())
//출력 결과 : 5.5
println(numbers.average())
범위 지정 함수
'수신 객체(reciever)'와 '수신 객체 지정 람다(block)'를 공통적으로 가지는 함수
⭐️⭐️모든 함수의 반환값 = 람다(block) 함수의 반환값 = 람다(block) 함수의 마지막 줄⭐️⭐️
let()
- fun <T, R> T.let(block: (T) -> R): R : 함수를 호출한 객체를 이어지는 람다 함수에 매개 변수로 전달하며, 람다 함수의 결과값 반환
- 불필요한 변수 선언 방지 가능
커스텀 뷰에서 패딩 값을 설정하는 코드
//단말기 환경에 맞게 패딩 값 계산
val padding = TypeValue.applyDimension(
TypeValue.COMPLEX_UNIT_DIP, 16f, resources.displayMetrics).toInt()
//계산된 패딩 값 변수를 이용해 패딩 값 설정
setPadding(padding, 0, padding, 0)
=>
//let을 사용하여 padding 변수 선언 없이 계산된 패딩 값을 함수의 인자로 전달 가능
TypeValue.applyDimension(TypeValue.COMPLEX_UNIT_DIP, 16f,
resources.displayMetrics).toInt().let {
setPadding(it, 0, it, 0) //계산된 값을 인자로 받으므로, it 키워드로 함수에 바로 대입 가능
}
null 값이 아닌 경우를 체크한 후 특정 작업을 수행하는 코드
fun doSomething(message: String?) {
//인자로 받은 message가 null이 아닌 경우에만 토스트로 메시지 표시
if (null != message) {
Toast.makeTest(this, message, Toast.LENGTH_SHORT).show()
}
}
=>
fun doSomeThing(message. String?) {
//message가 null이 아닌 경우에만 let 함수 호출
message?.let{
Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
}
}
apply()
- fun <T> T.apply(block: T.() -> Unit): T : 함수를 호출한 객체를 람다 함수의 리시버로 전달하며, 함수를 호출한 객체를 반환
- 람다 함수 내에서는 객체 이름 명시 없이 프로퍼티와 함수 직접 호출이 가능하므로, 프로퍼티에 값을 할당할 때 유용 ex) 객체 초기화
//param 객체의 여러 속성을 변경하기 위해 객체 이름을 계속하여 호출
val param = LineartLayout.LayoutParams(0, LinearLaout.LayoutParams.WRAP_CONTENT)
param.gravity = Gravity.CENTER_HORIZONTAL
param.weight = 1f
param.topMargin = 100
param.bottomMargin = 100
=>
//apply() 함수에 이어지는 블록에 param 객체를 리시버로 전달하므로, 객체 이름 없이 직접 해당 객체의 속성에 접근 가능
val param = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT).apply {
gravity = Gravity.CENTER_HORIZONTAL
weight = 1f
topMargin = 100
bottomMargin = 100
}
with()
- fun <T, R> with(reciever: T, block: T.() -> R): R : 매개변수로 받은 객체를 람다 함수의 리시버로 전달하며, 람다 함수의 결과값 반환
- 한 객체의 멤버에 반복해서 접근할 때 객체명을 일일히 명시하지 않고 멤버에 바로 접근 가능하며, 결과가 필요하지 않을 때 유용
- 안전한 호출(?.)을 지원하지 않으므로, 널 값이 아닌 것으로 확인된 객체에 이 함수를 사용해야 함
fun manipulateView(messageView: TextView) {
//함수의 인자로 받은 messageView의 여러 속성을 변경
with(messageView) {
//messageView 호출 없이 바로 속성값 변경 가능
text = "Hello, World"
gravity = Gravity.CENTER_HORIZONTAL
}
}
run()
- fun <R> run(block: () -> R): R : 람다를 실행하고, 람다 함수의 결과값을 반환 (람다 함수의 마지막줄 반환)
- 여러 임시 변수가 필요할 경우 또는 어떤 값을 계산해야할 때 유용
val padding = run {
//이 함수 블록 내부에서 선언하는 값들은 외부에 노출되지 않음
val defaultPadding = TypedValue.applyDimension(...)
val extraPadding = TypedValue.applyDimension(...)
//계산된 값 반환
defaultPadding + extraPadding
}
- fun <T, R> T.run(block: T.() -> R): R : 함수를 호출한 객체를 람다 함수의 리시버로 전달하며, 람다 함수의 결과값을 반환
- with() 함수와 유사하나 run() 함수는 안전한 호출 사용이 가능하므로 널 값일 수 있는 객체에 사용할 때 유용
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//엑티비티 생성 시, 기존에 저장된 값이 있는 경우 UI 복원 수행
savedInstanceState?.run {
//Bundle내에 저장된 값 추출
val selection = getInt("last_selection")
val text = getString("last_text")
//UI 복원 수행
...
}
}
🕊고차함수 참고자료
'Android' 카테고리의 다른 글
[kotlin] 안드버디 스터디 정리 -2 (0) | 2020.03.22 |
---|---|
[디자인패턴] MVVM 패턴 (MVVM의 구조와 동작, Repository pattern) (0) | 2020.03.22 |
[kotlin] 코틀린을 코틀린답게 (라이브러리 - 조건 확인 함수,컬렉션 생성 함수) (0) | 2020.03.08 |
[kotlin] 안드버디 스터디 정리 - 1 (0) | 2020.03.05 |
[kotlin] 코틀린을 코틀린답게 (함수,람다표현식) (0) | 2020.03.05 |