향후 정리 예정
가능하면 set따로 맵따로 파일 만드는게 좋을거같음
___
# 컬렉션
- array는 Collection 클래스를 상속받지 않았으므로 컬렉션에 미포함이라고 얘기하긴 하는데, map도 Collection을 상속받지 않았음에도 그냥 포괄적으로 컬렉션이라고 부르므로
어레이도 그냥 포괄적인 의미에서 컬렉션이라고 불러도 될 것으로 보임
# associate 3종
- list나 set같은걸 map으로 만들때 사용
- list l = {1, 2, 3}이 있을때 기준으로 설명
1) associateWith
l.associateWith { it * it } // 이건 키가 l내부의 값인 it이 되고, value가 괄호안에 있는 it * it이 된다.
2) associateBy
이건 associateWith랑 반대로
l.associateBy { it * it } // 이건 키가 괄호안에 있는 it * it이 되고, value가 l의 내부값인 it이 된다.
3) associate
이건 key value 둘 다 아예 새로 만들고 싶을때. 단 바로 연관짓는게 아니라 pair 객체를 새로 만들어서 넣는 방식이라 오버헤드가 있을 수 있음
l.associate { it to it * it } // key가 it이고 value가 it*it인 Pair 임시객체 생성해서 대입하는 방식
4) 오버로드된 associateBy
associate가 Pair 임시객체를 계속 만드느라 오버헤드가 생기니까 임시객체 없이 바로 넣는 방식도 있음
l.associateBy { {it}, {it*it} } // 이러면 key가 it이고 value가 it*it인걸로 바로바로 생성
활용처 정리하면
- key만 새로 만들고 값은 객체값 그대로 쓴다면 associateBy
- 객체값을 key로 쓰고 value는 새로 만들고 싶다면 associateWith
- 키와 값을 모두 새로 정할땐 오버로드된 associateBy
- 위 함수들로 표현하기 너무 어려우면 associate, 단 성능때문에 가급적 오버로드된 associateBy 사용
# 인덱스
numbers[10] 처럼 쓰면 out of index 오류날 수 있으니까 numbers.getOrNull(10) ?: 0 습관화하기
firstOrNull도 자주 쓰였음
___
7. mapOf
코틀린에도 Pair<A, B> 형식의 자료형이 있음
mapOf는 Pair 객체들을 만드는 것
val nameAgePairs = mapOf("철수" to 10, "영희" to 13)
-> 마찬가지로 제네릭이라 mapOf<String, Int>가 생략된 것
-> key가 "철수", value가 10인 Pair가 들어가는 것
특징은 중복 불허용 -> 이건 c++도 multiMap아니면 같으니
Pair 객체를 넣는거니까 Pair 객체로 넣어도 됨
val nameAgePairs2 = mapOf(Pair("철수" to 10), Pair("영희" to 13))
### 비어있는 Map 생성
val emptyPairs = emptyMap()
### 변경을 원하면 mutableMapOf 사용
val name = mutableMapOf("철수" to 10, "영희" to 13)
값 넣기
-> name.put("제임스" to 12)
-> name["제임스"] = 12
-> 이미 있는 키에 put이나 []로 넣으면 값 갱신
값 제거는 name.remove("제임스")
### key들만 가져오기
val keys = name.keys
### value들만 가져오기
val values = name.values
keys와 values는 배열 형태처럼 담기는데 출력해보면 [] 사이에 나오네
# 8. setOf
c++ set과 같음
유니크한 값만 가짐
setOf/mutableSetOf가 있음
val s = setOf(1, 3, 3, 3, 3, 3, 3, 4)
이런식으로 넣어도 print해보면 [1, 3, 4] 나옴
값 추가는 s.add(5)
값 제거는 s.remove(1)
※ 주의점
set은 값 추가 add고, map은 값 추가 put이다. 왜 이따구냐
※ 변경 가능한 set/map으로 만들기
toMutableSet(), toMutableMap()
```
val s = setOf(1, 3, 3, 3, 3, 3, 3, 4)
val ms = s.toMutableSetOf()
```
set과 foreach 사용법
val ms = mutableSetOf(1, 3, 3, 3, 3, 3, 3, 4)
val results = ms.withIndex()
results.forEach { r -> // r은 results에 들어있는 애들 하나하나, c++의 range based for 느낌으로
println("${r.index}, ${r.value}") // index와 value는 예약어였구나
}
결국 forEach가 range based for인건가?
# 확인 필요한 사항
set/map은 unique하게 중복처리안하는데 c++의 multiset/multimap은 코틀린에 없나?
# 10. 컬렉션 변환
컬렉션은 엄밀한 의미에서는 set/map/list를 의미한다.
왜냐하면 Collection이라는 클래스를 상속받은 클래스들이 저 셋이 있다.
array는 Collection을 상속받은게 아니라 엄밀한 의미에선 컬렉션은 아니지만 통상적으로 그냥 데이터 넣는 컨테이너들을 컬렉션이라고 부른다.
클래스 상속구조 참고 (https://soopeach.tistory.com/152)
그래서 컬렉션 변환은 List <-> MutableList나 List <-> set같은걸 의미
```
val ml = mutableListOf(1, 5, 7, 3, 3, 3, 3)
val l = ml.toList()
val l2 = mutableListOf(1, 5, 7, 3, 3, 3, 3)
val ml2 = l2.toMutableList()
println(l)
val s = l.toSet()
println(s)
```
기본적으로 원래객체.toSet 처럼 바꿀 컬렉션을 적으면 됨
### sortedSet
오름차순으로 정렬된 셋
### 내림차순 정렬
매개변수에 comparator라는걸 사용하면 된다.
val s = setOf(1, 5, 3, 2, 7)
val reverseOrderedSet = s.toSortedSet(comparator = Comparator.reverseOrder())
# 11. map + index
map은 add 대신 put, withIndex 대신 mapIndexed
그래서 map+index로 쓰려면 아래처럼 쓰면 된다.
```
val myFriends = listOf("a", "b", "c", "d")
val result = myFriends.mapIndexed { index, name ->
"index : $index, name : $name"
}
```
# 12. zip
두가지 컬렉션을 묶는 것
두개의 리스트를 zip하면 둘이 쌍을 짓게 됨(그냥 이어붙이는거 아님)
예를들어
```
val l1 = listOf(1, 2, 3, 7)
val l2 = listOf(4, 5, 6)
val l3 = l1.zip(l2)
```
위처럼하면 l3는 [(1, 4), (2, 5), (3, 6)]이 되고 7은 한쌍이 될게 없으니 안묶임
# 13. flatten
- flat : 납작한
즉 납작하게 만드는 것
flatten은 2차원 배열을 1차원으로 만드는 것
```
val l1 = listOf(1, 2, 3, 4)
val l2 = listOf(5, 6, 7, 8)
val l3 = listOf(l1, l2) // 이건 2차원 list
val flatList = l3.flatten()
println(flatList)
```
# 14. associate
컬렉션을 map으로 변형하는 것
map도 set처럼 중복불가(키는 고유해야하니까)
활용예시가 애매하긴한데 키는 고유한데 value는 최신으로 갱신이 필요할때 associateBy활용하는 예시가 젤 현실적이네
1) associateWith
- 키 : 배열안에 엘리멘트 하나
- 값 : 매개변수
2) associateBy
- 키 : 매개변수
- 값 : 배열안에 엘리멘트 하나
3) associate
- 직접 key to value형태로 작성하면 됨
val m : Map<String, String> = a.associate({it.name to it.age})
# 15. filter
컬렉션 내에서 원하는 엘리먼트들만 가져오는 것
```
val filteredList = l.filter ({
it.age < 20
})
```
위처럼 l.filter해서 결과가 여러개면 list를 반환하게 되는거고
그중 첫번째 한개만 반환받고 싶으면
```
val filteredList = l.filter ({
it.age < 20
}).first
```
만약 filter 조건이 복잡해서 함수화해야할 정도라면 저기 다 적기 좀 지저분할 수 있음
이땐 inline 함수로 함수 만들어서 사용
fun filterYoung(friend : Friend) : Boolean { // filter 판단 조건이 bool이기때문에 bool로 리턴해야 함
return friends.age < 20
}
이렇게 하고 val filterList = l.filter(::filterYoung) 처럼 사용하면 됨
::함수명 처럼 쓰면 인라인함수라는 뜻
enum class로 filter 인라인 함수 만들 수도 있음
```
enum class FriendFilter {
OLD, YOUNG;
fun filter(friend : Friend) : Boolean {
return when(this) {
OLD -> friend.age >= 20
YOUNG -> friend.age < 20
}
}
}
이렇게 쓰고 val filterList = l.filter(FriendFilter.OLD::filter)처럼 사용 가능
```
# 16. groupBy
묶어주는 것
리스트에 pair 여러개 넣을때 key가 같은거 여러개 넣을 수 있음
이 리스트를 map으로 만들때 key가 같은 애들끼리 묶어주는 것
이건 좀 필요할때 다시 봐야겟는데? 지금은 왜 필요한지 잘 못느끼겠음
groupBy도 있고 GroupingBy도 있음
# 17. reverse
뒤집는거
reverse(), reversed(), asReversed()가 있음
- reverse()는 자기 자신을 뒤집고 저장하는 것
- reversed()는 뒤집은걸 반환하는 것
- asReversed()도 뒤집은걸 반환하는데 원본과 연결되어 있음, 원본에 뭘 add하거나 asReversed()로 만든애한테 add하면 서로에게 영향을 줌
- asReversed()로 만든애한테 add로 젤 뒤에 뭘 넣으면 원본은 젤 앞에 뭐가 들어가게 됨
- 내부 방식이 값이 뒤집힌다기보다 인덱스가 뒤집히는 느낌이라
```
val nums = listOf(1, 2, 3)
val reversed = nums.reversed()
println(reversed) // [3, 2, 1]
```
# 18. drop
take와 반대되는 것
버리는 것
drop(10), dropLast(10)
# 19.take
drop과 반대되는 것
drop은 버리는것 take는 가져가는 것
```
val numbers : List<Int> = (1 .. 100).toList()
val t = numbers.take(10) // 1 ~ 10
val tl = numbers.takeLast(10) // 91 ~ 100
```
### takeLast
take는 앞에서 몇개, takeLast는 뒤에서 몇개
### takeWhile
true일동안 계속 take
```
val resultA = numbers.takeWhile ({
val condition = it < 30
condition
})
```
이러면 1부터 29까지 계속 돌면서 true니까 가져가서 resultA에 넣게 됨
뒤에서부터 반복문 돌리려면 takeLastWhile
### takeIf
이건 일부만 가져가는게 아니라 조건에 맞으면 다 가져가는거고, 아니면 null인것
```
val resultAA = numbers.takeIf({
it.contains(10)
})
```
근데 10을 포함하지 않으면 null 반환하니까 ?: listOf() 덧붙이면 없으면 빈리스트 반환 이런식으로 많이 씀
### takeUnless
이건 takeIf의 반대로 false여야 다 가져감
※ takeWhile, dropWhile은 filter로 할수도 있는데 왜 있냐
takeWhile, dropWhile은 인덱스 처음부터 false일때까지 쭉 도는 것
예를들어 list가 (1, 1, 1, 3, 1)인데 filter하면 3 하나만 남겠지만, dropWhile하면 1이면 버린다로 한다면 3에서 멈추니까 [3, 1]이 된다.
