2011-02-17 34 views
9

đây là một chút của một câu hỏi chung nhưng tôi đã tự hỏi nếu có ai có thể tư vấn cho tôi về những gì sẽ là lợi thế của làm việc với mảng vs arrayseq. Từ những gì tôi đã thấy Array là đại diện của Scala về mảng java và không có quá nhiều thành viên trong api của nó trong khi Arrayseq dường như chứa api phong phú hơn nhiều. cảm ơn vì lời khuyên nào.scala - array vs arrayseq

Trả lời

32

Thực tế, có bốn lớp khác nhau mà bạn có thể lựa chọn để có được chức năng mảng giống như có thể thay đổi.

Array + ArrayOps 
WrappedArray 
ArraySeq 
ArrayBuffer 

Array là một mảng Java cũ đơn giản. Đây là cách tốt nhất để truy cập cấp thấp đối với các mảng nguyên thủy. Không có phí. Ngoài ra nó có thể hoạt động giống như các bộ sưu tập Scala nhờ chuyển đổi ẩn thành ArrayOps, lấy mảng bên dưới, áp dụng phương thức thích hợp và, nếu thích hợp, trả về một mảng mới. Nhưng kể từ khi ArrayOps không phải là chuyên ngành cho nguyên thủy, nó chậm (chậm như boxing/unboxing luôn luôn là).

WrappedArray là một mảng Java cũ, nhưng được gói trong tất cả các tính năng bộ sưu tập của Scala. Sự khác biệt giữa nó và ArrayOpsWrappedArray trả về một WrappedArray - ít nhất bạn không có phí tổn phải lặp lại một lần nữa các mảng nguyên thủy Java của bạn cho mỗi thao tác. Thật tốt khi sử dụng khi bạn đang làm rất nhiều interop với Java và bạn cần phải vượt qua trong các mảng Java cũ, nhưng ở phía Scala bạn cần phải thao tác chúng một cách thuận tiện.

ArraySeq lưu trữ dữ liệu của nó trong một mảng Java cũ, nhưng không còn lưu trữ mảng nguyên thủy nữa; mọi thứ đều là một mảng các đối tượng. Điều này có nghĩa là nguyên thủy được đóng hộp trên đường đi. Điều đó thực sự thuận tiện nếu bạn muốn sử dụng các nguyên thủy nhiều lần; vì bạn đã có các bản sao đóng hộp được lưu trữ, bạn chỉ phải mở hộp chúng, không phải hộp và bỏ chúng trên mọi hoạt động chung.

ArrayBuffer hoạt động như một mảng nhưng bạn có thể thêm và xóa các phần tử khỏi mảng đó. Nếu bạn định đi đến tận ArraySeq, tại sao bạn không có sự linh hoạt trong việc thay đổi độ dài khi bạn đang ở đó?

+0

điều này phải là một phần của mọi (và bất kỳ) tài liệu scala xung quanh bộ sưu tập. +1 – Dragonborn

0

Khi bạn quan sát chính xác, ArraySeq có API phong phú hơn vì nó được lấy từ IndexedSeq (và vân vân) trong khi mảng là biểu diễn trực tiếp của các mảng Java.

Mối quan hệ giữa cả hai có thể gần bằng với mối quan hệ của ArrayList và mảng trong Java.

Do đó là API, tôi khuyên bạn nên sử dụng ArraySeq trừ khi có lý do cụ thể không làm như vậy. Sử dụng toArray(), bạn có thể chuyển đổi thành một mảng bất kỳ lúc nào.

+2

Không phải vậy! Họ có [cùng một API ...] (http://www.scala-lang.org/api/current/scala/collection/mutable/ArrayLike.html) –

+0

Ah, không thấy chuyển đổi tiềm ẩn –

6

Từ scala-lang.org forum:

Array [T] - Lợi ích: Native, nhanh chóng - Hạn chế: Một vài phương pháp (chỉ áp dụng, cập nhật, chiều dài), cần phải biết T tại compile- thời gian, bởi vì Java bytecode đại diện (char [] khác nhau từ int [] khác nhau từ Object [])

ArraySeq [T] (lớp trước đây gọi như GenericArray [T]): - Lợi ích: Vẫn còn được hỗ trợ bởi một mảng gốc, không cần để biết bất cứ điều gì về T tại biên dịch-thời gian (new ArraySeq [T] "chỉ hoạt động", ngay cả khi không có gì là biết về T), bộ đầy đủ các phương pháp SeqLike, loại phụ của Seq [T] - Giới hạn: được hỗ trợ bởi một mảng [AnyRef], bất kể của T là gì (nếu T là nguyên thủy, sau đó yếu tố sẽ được đóng hộp/không có hộp bọc trên cách của họ trong hoặc ra khỏi sự ủng hộ mảng)


ArraySeq [Bất kỳ] là nhanh hơn nhiều so Array [Bất kỳ] khi xử lý nguyên thủy. Trong bất kỳ mã nào, bạn có Mảng [T], trong đó T không phải là <: AnyRef, bạn sẽ nhận được hiệu suất nhanh hơn trong ArraySeq.

+2

Bạn chắc chắn có ngược lại - như trích dẫn của bạn nói, ArraySeq hộp và unboxes nguyên thủy. –

+0

@Jim - Vì vậy, không có 'Array [Any] ', nó chỉ làm nó chậm hơn. Để có được hiệu năng từ 'Array', nó phải được gõ là' Array [Int] ', hoặc bất kỳ nguyên thủy nào khác mà bạn đang sử dụng. –

+0

@Kevin Nhưng ông nói "Trong bất kỳ mã nào bạn có Array [T], trong đó T không phải là <: AnyRef, bạn sẽ nhận được hiệu suất nhanh hơn trong ArraySeq" ... điều đó không đúng nếu T là Int. –

8

Array là đại diện trực tiếp của Java Array và sử dụng cùng một mã byte tương tự trên JVM.

Lợi thế của mảng là chỉ loại bộ sưu tập trên JVM không phải loại bỏ xóa, mảng cũng có thể trực tiếp giữ nguyên thủy mà không cần đấm bốc, điều này có thể làm cho chúng rất nhanh trong một số trường hợp.

Ngoài ra, bạn sẽ nhận được hành vi hiệp phương sai mảng của Java. (Nếu bạn vượt qua ví dụ:một Array[Int] một số lớp Java nó có thể được gán cho một biến kiểu Array[Object] mà sau đó sẽ ném một ArrayStoreException trên cố gắng để thêm bất cứ điều gì đó không phải là một int.)

ArraySeq hiếm khi được sử dụng ngày nay, đó là chi tiết của một di tích lịch sử tạo tác từ các phiên bản cũ của Scala đã xử lý các mảng khác nhau. Thấy như bạn phải đối phó với boxing anyway, bạn gần như chắc chắn để tìm thấy rằng một loại bộ sưu tập là một phù hợp hơn cho yêu cầu của bạn.

Nếu không ... Mảng có chính xác cùng một API như ArraySeq, nhờ chuyển đổi ẩn từ Array thành ArrayOps.

Trừ khi bạn có nhu cầu cụ thể về các thuộc tính duy nhất của mảng, hãy cố gắng tránh chúng. Xem This Talk at around 19:30 hoặc This Article để biết loại sự cố mà Mảng có thể giới thiệu.

Sau khi xem video mà, thật thú vị khi lưu ý rằng Scala sử dụng Seq cho varargs :)