[Scala] - day 5 : Collections trong Scala [phần I] - List ,Map và Set


Collections là 1 cấu trúc data tập hợp của một hoặc nhiều giá trị như là arrays, lists, maps, sets, và trees. Hầu hết các ngôn ngữ lập trình đều có những cấu trúc collections của riêng mình bởi vì công việc lập trình hiện đại cần đến những cấu trúc dữ liệu như vậy.

List

Hãy tạo ra 1 immutable list, ta có thể tạo ra 1 list bằng cách khởi gọi function List và truyền vào đó những value trong list như những parameter, nếu ngôn ngữ của tôi khiến bạn khó hiểu hãy xem lại về function type ở bài trước.
scala> val listSo = List(1,5,7,9)
listSo: List[Int] = List(1, 5, 7, 9)
scala> val listHoaQua = List("Bưởi","Bòng","Cam","Quýt")
listHoaQua: List[String] = List(Bưởi, Bòng, Cam, Quýt)
scala> val listLinhTinh = List(22,"ba b")
listLinhTinh: List[Any] = List(22, ba b)
scala> val listRong = List()
listRong: List[Nothing] = List()
Như bạn có thể thấy Scala sẽ tự kiểm tra kiểu dữ liệu bạn truyền vào và cho ra kiểu List phù hợp với data đó ,giờ bạn hãy thử khai báo 1 List[Int]  nhưng value truyền vào lại là String.
Có 2 cách để bạn truy cập đến các phần tử trong list :
 - Sử dụng head, tail  và last : listNaoDo.head and listNaoDo.tail
 - Sử dụng index chỉ rõ vị trí của phần tử muốn lấy : listNaoDo(index)
***) cả 2 phương pháp trên khi dùng với list rỗng sẽ throw Exception
head trả về phần tử đầu tiên của list.
scala> listHoaQua.head
res6: String = Bưởi
tail trả về list gồm  toàn bộ phần tử đằng sau phần tử đầu tiên
scala> listHoaQua.tail
res7: List[String] = List(Bòng, Cam, Quýt)
bạn hãy thử với last xem chúng ta có được kết quả thế nào.
hoặc có thể chỉ chính xác vị trí cần lấy,vị trí đầu tiên là 0.
scala> listHoaQua(1)
res8: String = Bòng
giờ đến lượt bạn,thử truy xuất phần tử của 1 list rỗng hay tới 1 vị trí không có phần tử nào.
Bạn còn nhớ day 3 chúng ta bàn về loop trong scala, ta thử duyệt list bằng loop :
scala> for (hoaQua <- listHoaQua) { println(hoaQua)}
Bưởi
Bòng
Cam
Quýt
Còn ở day-4 bạn đã biết đến higher-order functions , ở đây tôi muốn giới thiệu đến các bạn 3 higher-order functions rất hữu ích cho list.
 - foreach() : là 1 procedure (các bạn nhớ procedure không,ở day-3 nhé) nó nhận vào 1 function và thực hiện với từng phần tử trong list và tất nhiên nó trả về 1 Unit - procedure mà .
 - map() : nhận vào 1 function và convert list phần tử đó thành giá trị khác hay kiểu khác.
 - reduce() : nhận vào 1 function có nhiệm vụ combine 2 phần tử của list thành 1 và cứ thế cho đến cuối list.

Với foreach :
scala> listSo.foreach((x: Int)=> println("đây là số : "+ x))
đây là số : 1
đây là số : 5
đây là số : 7
đây là số : 9
ta thử trả về x với mỗi lần lặp và gán kết quả của vòng foreach với 1 biến
scala> val temp = listSo.foreach((x: Int)=> { println("đây là số : "+ x);x})
đây là số : 1
đây là số : 5
đây là số : 7
đây là số : 9
temp: Unit = ()
Bạn thấy đấy, dù bạn trả về gì đi nữa thì kết quả là 1 Unit.Nếu mục đích của bạn là xử lý list và trả 1 kết quả nào đó thì không nên dùng foreach.

Với map:
listSo.map((x: Int) => x*2 )
res9: List[Int] = List(2, 10, 14, 18)
như bạn thấy tôi gọi function map và truyền vào 1 function có dạng Int => Int ,nhận vào 1 số Int và nhân đôi số đó lên,kế quả tôi nhận được từ map là 1 list mới lưu vào value hệ thống res9 với tất cả phần tử của list dc map nhân đôi lên.

Với reduce :
scala> listSo.reduce((a: Int, b: Int) =>{println("đây là số "+a+" và số "+b); a + b})
đây là số 1 và số 5
đây là số 6 và số 7
đây là số 13 và số 9
res10: Int = 22
Tôi gọi hàm reduce và truyền vào 1 function có nhiệm vụ nhận vào 2 số Int và trả về số bằng tổng 2 số đó,với mỗi lần như vậy tôi in ra số lấy được từ list cần xử lý,bạn thấy gì không,với mỗi lần được khởi gọi reduce đưa 2 số từ list vào làm param và kết quả của function là 1 value thay cho 2 số trước đó.Bài tập của bạn là hãy tạo 1 list chỉ có 1 phần tử và dùng reduce như tôi dùng và xem kết quả có gì nhé.

Set

Với Set ta có 1 cấu trúc và cách sử dụng tương tự List, nó có 2 đặc điểm chính sau :
 - Bất biến : bạn không thể thay đổi 1 Set
 - Các phần tử trong Set là unique
scala> val unique = Set(10, 20, 30, 20, 20, 10)
unique: scala.collection.immutable.Set[Int] = Set(10, 20, 30) 
Thấy không,bất biến và các phần tử là duy nhất nhé.

Map

Với Map, nó được dùng để lưu trữ 1 hay nhiều cặp immutable key-value và tất nhiên khi tạo 1 Map bạn phải chỉ rõ key và value bằng cách sử dụng  ( -> ).

scala> val nguoiYeuCu = Map("em Ha" -> "béo","em Linh"->"gầy","em nào đó"->"chả rõ")
nguoiYeuCu: scala.collection.immutable.Map[String,String] = Map(em Ha -> béo, em Linh -> gầy, em nào đó -> chả rõ) 
scala> nguoiYeuCu("em Ha")
res23: String = béo
Giờ bài tập của bạn là hãy thử foreach,map và reduce với Set và Map nhé
List,Set và Map đi kèm cũng rất nhiều method để convert cũng như xử lý mà ta không cần tốn công duyệt chúng bằng các vòng lặp,tôi sẽ có 1 bài riêng cho phần đó,trước mắt tôi chỉ muốn giới thiệu với các bạn cái nhìn tổng quan về chúng.
Hẹn gặp lại ngày mai và ta cùng tìm hiểu về mutable collections.
Scala Collections

Comments