17.1 시퀀스
: 시퀀스 타입은 순서가 정해진 데이터 그룹을 가지고 작업할 수 있게 해준다.
< 리스트 >
: 변경 불가능한 연결 리스트로 원소를 앞 부분에 빠르게 추가/삭제할 수 있지만 리스트를 순차적으로 따라가야해 임의의 위치에 접근할 때 빠르지 않다.
: 첫 번째 원소를 빠르게 추가/삭제할 수 있는 건 패턴 매치를 잘할 수 있다는 뜻
: 불변성은 리스트를 복사하지 않아도 되기 때문에 효율적이면서 올바른 알고리즘 개발에 도움
< 배열 >
: 임의의 위치에 있는 원소에 효율적으로 접근
: 배열은 '[]'가 아니라 '()'에 인덱스를 넣어서 원소 접근
< 리스트 버퍼 >
: 변경 가능한 객체로 상수 시간에 원소를 앞/뒤로 추가 가능
* 리스트로 끝부분에 원소를 추가하려면 리스트의 앞에 원소를 차례로 추가해 뒤집힌 리스트를 만들고 reverse 호출
- append , "+=" : 원소를 뒤에 추가
- prepend, "+=:" : 연산자를 통해 원소를 앞에 추가
- toList : ListBuffer => List
- 잠재적인 스택 오버플로를 피하기 위해 List 대신 ListBuffer 사용(재귀, for, while에서)
scala> import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer scala> val buf = new ListBuffer[Int] buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer() scala> buf += 1 res4: buf.type = ListBuffer(1) scala> buf += 2 res5: buf.type = ListBuffer(1, 2) scala> buf res6: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2) scala> 3 +=: buf res7: buf.type = ListBuffer(3, 1, 2) scala> buf.toList res8: List[Int] = List(3, 1, 2) |
< 배열 버퍼 >
: 끝 부분과 시작 부분에 원소를 추가/삭제할 수 있다는 점만 제외하면 배열과 같다.
: 새 원소 추가/삭제하는 데 평균적으로 상수시간이 걸리나, 때때로 버퍼의 내용을 저장하기 위해 새로운 배열을 할당해야 하기 때문에 종종 선형 시간이 걸린다.
scala> import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer scala> val buf = new ArrayBuffer[Int]() // 생성할 때 타입 인자 지정, 크기는 필요에 따라 자동 조절 buf: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() scala> buf += 12 res9: buf.type = ArrayBuffer(12) scala> buf += 15 res10: buf.type = ArrayBuffer(12, 15) |
< 문자열(StringOps를 통해서) >
: Predef 에 String을 StringOps로 바꾸는 암시적 변환이 있어 문자열을 시퀀스처럼 다룰 수 있다.
scala> def hasUpperCase(s: String) = s.exists(_.isUpper) hasUpperCase: (s: String)Boolean scala> hasUpperCase("Robert Frost") res14: Boolean = true |
17.2 집합과 맵
: 스칼라의 Set과 Map은 변경 불가능한 객체와 변경 가능한 객체 존재
: 모든 스칼라의 소스 파일에 자동으로 임포트하는 Predef 객체에 변경 불가능한 맵, 집합이 정의되어 있음
object Predef { type Map[A, +B] = collection.immutable.Map[A, B] // Map 타입 type Set[A] = collection.immutable.Set[A] val Map = collection.immutable.Map // Map 싱글톤 객체 val Set = collection.immutable.Set // ... } |
< 집합의 사용 >
: 집합은 특정 객체를 최대 하나만 들어가도록 보장한다
< Map 의 사용 >
: 어떤 값과 집합의 각 원소 사이에 연관 관계를 만든다.
< 디폴트 집합과 맵 >
: scala.collection.mutable.Set() 팩토리 메소드는 내부적으로 해시 테이블을 사용하는 scala.collection.mutable.HashSet을 반환한다. scala.collection.mutable.Map() 팩토리 메소드도 ~.HashMap을 반환한다.
: 변경 불가능한 집합과 맵은 팩토리에 얼마나 많은 원소를 전달하느냐에 따라 달라진다.(원소가 5개 보다 적은 집합에 대해서는 성능을 극대화하기 위해 특정 크기의 집합만 담당하는 특별한 클래스를 사용한다.)
< 정렬된 집합과 맵 >
- 정해진 순서대로 원소를 반환하는 이터레이터를 제공하는 맵이나 집합을 사용할 때 SortedSet, SortedMap 트레이트 사용
- SortedSet과 SortedMap 구현이 TreeSet, TreeMap
- 순서를 커스텀하게 정할 때, 정렬된 집합이나 정렬된 맵의 키에 Ordered 트레이트를 혼합하거나 암시적으로 Ordered 트레이트로 변환 가능해야 한다.
scala> import scala.collection.immutable.TreeSet
scala> import scala.collection.immutable.TreeMap |
17.3 변경 가능 컬렉션과 변경 불가능 컬렉션
: mutable, immutable 중 어떤 것을 선택해야 할지 모르겠다면, immutable로 시작하고 나중에 필요에 따라 바꾸는 게 좋다. ( immutable이 mutable 보다 프로그램 추론이 쉽다. )
: mutable을 먼저 사용한다면 코드가 복잡하고 추론하기 어려울 때 immutable 고려( 변경 가능 컬렉션의 복사본을 언제 만들어야 할지 고민되거나, 누가 갖고 있는지나 누구에게 포함되어 있는지 많이 생각해야 한다면 )
: 컬렉션에 저장할 원소의 수가 적을 경우 immutable이 mutable보다 더 작게 메모리를 사용
Ex. 변경 가능한 빈 HashMap은 80바이트이고 원소를 하나 추가할 때마다 16바이트가 더 든다. 변경 불가능한 빈 맵은 싱글톤 객체 하나를 모든 참조가 공유하기 때문에 포인터 필드 하나만큼의 메모리만 필요하다.
: 변경 불가능한 맵/집합은 크기가 4일 때까지 단일 객체(Set1~Set4, Map1~Map4)를 사용한다. 단일 객체 크기는 16~40 바이트 정도로 변경 가능한 맵/집합보다 공간이 훨씬 작다. => 많은 컬렉션이 작은 크기라면 컬렉션을 변경 불가능하게 만드는 것이 공간을 절약하고 성능을 향상하는 중요한 선택
: 스칼라에서는 맵/집합에 데이터를 조금 저장하는 것을 추구, immutable은 값을 매번 복사 => 메모리를 많이 잡아먹음 => 별도 객체
" 변경 불가능한 맵 " var capital = Map("US" -> "Washington", "France" -> "Paris") |
" 변경 가능한 맵 " import scala.collection.mutable.Map // only change needed! |
17.4 컬렉션 초기화
: 일반적인 초기화 방법은 초기 원소를 컬렉션 동반 객체의 팩토리 메소드에 넘기는 것(apply 메소드 호출로 변환)
: 동반 객체의 팩토리 메소드에 타입 명시 가능
scala> import scala.collection.mutable import scala.collection.mutable scala> val stuff = mutable.Set(42) stuff: scala.collection.mutable.Set[Int] = Set(42) scala> stuff += "abracadabra" :15: error: type mismatch; found : java.lang.String("abracadabra") required: Int stuff += "abracadabra" ^ scala> val stuff = mutable.Set[Any](42) // 타입 명시 stuff: scala.collection.mutable.Set[Any] = Set(42) |
: 어떤 컬렉션을 다른 컬렉션으로 초기화하는 경우
scala> val colors = List("blue", "yellow", "red", "green") colors: List[java.lang.String] = List(blue, yellow, red, green) scala> import scala.collection.immutable.TreeSet import scala.collection.immutable.TreeSet scala> val treeSet = TreeSet(colors) :15: error: could not find implicit value for parameter ord: Ordering[List[java.lang.String]] val treeSet = TreeSet(colors) ^ scala> val treeSet = TreeSet[String]() ++ colors treeSet: scala.collection.immutable.TreeSet[String] = TreeSet(blue, green, red, yellow) |
< 배열이나 리스트로 바꾸기 >
: 배열이나 리스트로 바꿀 때 toList, toArray를 호출하면 된다.
: toList, toArray를 호출했을 때 각 원소의 순서는 호출하는 컬렉션이 생성한 이터레이터가 돌려주는 원소의 순서와 같다.
scala> treeSet.toList res50: List[String] = List(blue, green, red, yellow) |
< 변경 가능한 집합(맵)과 변경 불가능 집합(맵) 사이의 변환 >
: empty 메소드를 사용해 새로운 타입의 컬렉션 생성 => "++" , "++=" 연산자를 사용해 원소 추가
scala> import scala.collection.mutable import scala.collection.mutable scala> treeSet res52: scala.collection.immutable.TreeSet[String] = TreeSet(blue, green, red, yellow) scala> val mutaSet = mutable.Set.empty ++= treeSet mutaSet: scala.collection.mutable.Set[String] = Set(yellow, blue, red, green) scala> val immutaSet = Set.empty ++ mutaSet immutaSet: scala.collection.immutable.Set[String] = Set(yellow, blue, red, green) |
17.5 튜플
: 배열, 리스트와 달리 여러 타입의 원소를 넣을 수 있다. => 데이터만 저장하는 단순한 클래스를 정의해야 하는 번거로움을 덜 수 있다.
: 각기 다른 타입의 객체를 결합할 수 있기 때문에 Traversable을 상속 X
: 튜플 원소에 접근할 대는 _n 메소드 사용(인덱스가 1부터 시작)
scala> longest = ("quick", 1) scala> longest._1 // 첫 번째 원소
scala> val (word, idx) = longest // 패턴 매치 |
: 튜플은 'A 하나와 B 하나' 수준을 넘지 않는 데이터를 한데 묶을 때 아주 유용
: 결합에 어떤 의미가 있거나 결합에 어떤 메소드를 추가하기 원한다면 클래스를 생성하는 게 좋다.(Ex. 연,월,일 => Date 클래스) => 코드 이해가 쉽고, 컴파일러가 제공하는 기능을 통해 오류를 쉽게 찾을 수 있다.
'스칼라' 카테고리의 다른 글
스칼라 19장 타입 파라미터화, 변성(Programming in Scala, 3rd) (0) | 2019.06.07 |
---|---|
스칼라 18장 변경 가능한 객체(Programming in Scala, 3rd) (0) | 2019.06.07 |
스칼라 16장 리스트(Programming in Scala, 3rd) (0) | 2019.06.02 |
스칼라 15장 케이스 클래스와 패턴 매치(Programming in Scala, 3rd) (0) | 2019.06.02 |
스칼라 14장 단언문과 테스트(Programming in Scala, 3rd) (0) | 2019.06.02 |