Sự khác biệt giữa Seq và Danh sách trong Scala


299

Tôi đã thấy trong nhiều ví dụ rằng đôi khi một Seq đang được sử dụng, trong khi những lần khác là Danh sách ...

Có sự khác biệt nào, ngoài loại trước đây là loại Scala và Danh sách đến từ Java không?

Câu trả lời:


408

Theo thuật ngữ Java, Scala Seqsẽ là Java Listvà Scala Listsẽ là Java LinkedList.

Lưu ý rằng đó Seqlà một trait, tương đương với Java interface, nhưng tương đương với các phương thức bảo vệ sắp tới. Scala's Listlà một lớp trừu tượng được mở rộng bởi Nil::, đó là những triển khai cụ thể của List.

Vì vậy, trong đó Java Listlà một interface, Scala Listlà một triển khai.

Ngoài ra, Scala Listlà bất biến, đó không phải là trường hợp LinkedList. Trong thực tế, Java không có tương đương với các bộ sưu tập bất biến (điều chỉ đọc chỉ đảm bảo đối tượng mới không thể thay đổi, nhưng bạn vẫn có thể thay đổi đối tượng cũ và do đó, chỉ "chỉ đọc").

Scala Listđược tối ưu hóa cao bởi trình biên dịch và thư viện và đây là loại dữ liệu cơ bản trong lập trình chức năng. Tuy nhiên, nó có những hạn chế và nó không đủ để lập trình song song. Những ngày này, Vectorlà một lựa chọn tốt hơn List, nhưng thói quen là khó phá vỡ.

Seqlà một khái quát tốt cho các chuỗi, vì vậy nếu bạn lập trình cho các giao diện, bạn nên sử dụng nó. Lưu ý rằng có thực sự ba trong số đó là: collection.Seq, collection.mutable.Seqcollection.immutable.Seq, và nó là một trong những thứ hai đó là "mặc định" nhập khẩu vào phạm vi.

Cũng có GenSeqParSeq. Các phương thức sau chạy song song khi có thể, trong khi phương thức trước là cha mẹ của cả hai SeqParSeq, là một khái quát hóa phù hợp khi sự song song của mã không thành vấn đề. Cả hai đều tương đối mới được giới thiệu, vì vậy mọi người chưa sử dụng chúng nhiều.


3
RE "Java không có tương đương với các bộ sưu tập bất biến" , mặc dù Stringkhông phải là một bộ sưu tập, nó là một ví dụ về các lớp bất biến quen thuộc với các lập trình viên Java.
huynhjl

15
@huynhjl Đó là bên cạnh điểm. Tôi đã vẽ tương đồng giữa những gì tồn tại trong Java và những gì tồn tại trong Scala và không có bất kỳ khái niệm nào về các bộ sưu tập có thể thay đổi / bất biến trong Java.
Daniel C. Sobral

2
Java thực sự có tương đương với các bộ sưu tập bất biến. Nó không phải là "được quảng cáo tốt" nhưng nó ở đó và khi bạn sử dụng thuốc generic rất nhiều, bạn có khả năng bị ảnh hưởng UnsupportedOperationExceptionvì điều này. Để tạo một danh sách bất biến trong Java bạn sử dụng Collections.unmodifiableList () và tương tự có phương pháp khác để Sets, Maps, vv docs.oracle.com/javase/6/docs/api/java/util/...
jbx

27
@jbx Không đúng. Nếu bạn sử dụng các phương thức này, bạn sẽ nhận được một cái gì đó một đối tượng sẽ ném ngoại lệ vào các phương thức sửa đổi nó, nhưng không phải là một đối tượng bất biến . Nếu đối tượng ban đầu được sửa đổi sau khi đối tượng không thể thay đổi được tạo, đối tượng không thể thay đổi sẽ phản ánh điều đó. Vì vậy, không thể thay đổi, có, bất biến, không.
Daniel C. Sobral

3
@jbx Phương thức nhận không thể giữ tham chiếu đến bộ sưu tập mà nó nhận được và cho rằng nó sẽ không bao giờ thay đổi và không có loại nào trong thư viện Java tiêu chuẩn sẽ đảm bảo rằng - đó là tính bất biến. Vì vậy, ví dụ, phương thức nhận đó không thể đảm bảo an toàn cho luồng. Và điều này thậm chí không chạm vào các đặc điểm liên tục được kích hoạt bởi tính bất biến. Không có tất cả điều đó, nó không thể được gọi là "tương đương".
Daniel C. Sobral

81

Một Seq là một Iterable mà có một trật tự xác định các yếu tố. Trình tự cung cấp một phương pháp apply()để lập chỉ mục, từ 0 đến chiều dài của trình tự. Seq có nhiều lớp con bao gồm Queue, Range, List, Stack và LinkedList.

Một Danh sách là một Seq đó được thực hiện như một danh sách liên kết không thay đổi. Nó được sử dụng tốt nhất trong các trường hợp có mẫu truy cập vào trước xuất trước (LIFO).

Dưới đây là hệ thống phân cấp lớp bộ sưu tập hoàn chỉnh từ Câu hỏi thường gặp về Scala :

nhập mô tả hình ảnh ở đây


2
Mảng ở đâu (và ArrayBuffer)? Nó không phải là loại lặp đi lặp lại
Peter Krauss

23

Seqlà một đặc điểm Listthực hiện.

Nếu bạn xác định vùng chứa của mình là Seq, bạn có thể sử dụng bất kỳ vùng chứa nào thực hiện Seqtính trạng.

scala> def sumUp(s: Seq[Int]): Int = { s.sum }
sumUp: (s: Seq[Int])Int

scala> sumUp(List(1,2,3))
res41: Int = 6

scala> sumUp(Vector(1,2,3))
res42: Int = 6

scala> sumUp(Seq(1,2,3))
res44: Int = 6

Lưu ý rằng

scala> val a = Seq(1,2,3)
a: Seq[Int] = List(1, 2, 3)

Chỉ là một bàn tay ngắn cho:

scala> val a: Seq[Int] = List(1,2,3)
a: Seq[Int] = List(1, 2, 3)

nếu loại vùng chứa không được chỉ định, cấu trúc dữ liệu cơ bản mặc định là List.


18

Trong Scala, Danh sách kế thừa từ Seq, nhưng thực hiện Sản phẩm ; đây là định nghĩa đúng của Danh sách :

sealed abstract class List[+A] extends AbstractSeq[A] with Product with ...

[Lưu ý: các thực tế định nghĩa . Là một chút cắn phức tạp hơn, để phù hợp với và sử dụng khuôn khổ bộ sưu tập rất mạnh mẽ của Scala]


0

Như @ daniel-c-sobral đã nói, List mở rộng đặc điểm Seq và là một lớp trừu tượng được thực hiện bởi scala.collection.immutable.$colon$colon(hoặc ::viết tắt), nhưng về mặt kỹ thuật, hãy nhớ rằng hầu hết các danh sách và seq chúng tôi sử dụng đều được khởi tạo ở dạng Seq(1, 2, 3)hoặc List(1, 2, 3)cả hai đều trả về scala.collection.immutable.$colon$colon, do đó người ta có thể viết:

var x: scala.collection.immutable.$colon$colon[Int] = null
x = Seq(1, 2, 3).asInstanceOf[scala.collection.immutable.$colon$colon[Int]]
x = List(1, 2, 3).asInstanceOf[scala.collection.immutable.$colon$colon[Int]]

Kết quả là, tôi tranh luận hơn điều duy nhất quan trọng là các phương thức bạn muốn đưa ra, ví dụ, để trả trước bạn có thể sử dụng ::từ Danh sách mà tôi thấy dư thừa +:từ Seq và cá nhân tôi mặc định dính vào Seq.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.