Sự khác biệt giữa các loại Danh sách và Mảng trong Kotlin


189

Sự khác biệt giữa ListArraycác loại là gì?
Dường như có thể thực hiện các hoạt động tương tự với chúng (vòng lặp, biểu thức lọc, v.v.), có sự khác biệt nào trong hành vi hoặc cách sử dụng không?

val names1 = listOf("Joe","Ben","Thomas")
val names2 = arrayOf("Joe","Ben","Thomas")

for (name in names1)
    println(name)
for (name in names2)
    println(name)

Câu trả lời:


279

Mảng và danh sách (đại diện bởi List<T>và phân nhóm của nó MutableList<T>) có nhiều điểm khác biệt, đây là những điểm quan trọng nhất:

  • Array<T>là một lớp có triển khai đã biết: đó là vùng bộ nhớ có kích thước cố định tuần tự lưu trữ các mục (và trên JVM, nó được biểu diễn bằng mảng Java ).

    List<T>MutableList<T>là các giao diện có các cách triển khai khác nhau : ArrayList<T>, LinkedList<T>v.v. Biểu diễn bộ nhớ và logic hoạt động của các danh sách được xác định trong triển khai cụ thể, ví dụ: lập chỉ mục trong một LinkedList<T>liên kết và mất thời gian O (n) trong khi ArrayList<T>lưu trữ các mục của nó trong một mảng được phân bổ động.

    val list1: List<Int> = LinkedList<Int>()
    val list2: List<Int> = ArrayList<Int>()
  • Array<T>có thể thay đổi (có thể thay đổi thông qua bất kỳ tham chiếu nào đến nó), nhưng List<T>không có phương thức sửa đổi (đây là chế độ xem chỉ đọcMutableList<T> hoặc thực hiện danh sách không thay đổi ).

    val a = arrayOf(1, 2, 3)
    a[0] = a[1] // OK
    
    val l = listOf(1, 2, 3)
    l[0] = l[1] // doesn't compile
    
    val m = mutableListOf(1, 2, 3)
    m[0] = m[1] // OK
  • Mảng có kích thước cố định và không thể mở rộng hoặc thu nhỏ giữ lại danh tính (bạn cần sao chép một mảng để thay đổi kích thước nó). Đối với các danh sách, MutableList<T>addremovechức năng, để nó có thể tăng và giảm kích thước của nó.

    val a = arrayOf(1, 2, 3)
    println(a.size) // will always be 3 for this array
    
    val l = mutableListOf(1, 2, 3)
    l.add(4)
    println(l.size) // 4
  • Array<T>bất biến trênT ( Array<Int>không Array<Number>), tương tự cho MutableList<T>, nhưng List<T>là covariant ( List<Int>is List<Number>).

    val a: Array<Number> = Array<Int>(0) { 0 } // won't compile
    val l: List<Number> = listOf(1, 2, 3) // OK
  • Mảng được tối ưu hóa cho nguyên thủy: có riêng biệt IntArray, DoubleArray, CharArrayvv được ánh xạ tới mảng nguyên thủy Java ( int[], double[], char[]), không đóng hộp những ( Array<Int>được ánh xạ tới Java Integer[]). Danh sách nói chung không có các triển khai được tối ưu hóa cho các nguyên thủy, mặc dù một số thư viện (bên ngoài JDK) cung cấp các danh sách được tối ưu hóa nguyên thủy.

  • List<T>MutableList<T>được ánh xạ các loại và có hành vi đặc biệt trong Java khả năng tương tác (Java List<T>được nhìn thấy từ Kotlin là một trong hai List<T>hoặc MutableList<T>). Mảng cũng được ánh xạ, nhưng chúng có các quy tắc khác về khả năng tương tác Java.

  • Một số loại mảng nhất định được sử dụng trong các chú thích (mảng nguyên thủy Array<String>và mảng có enum classmục) và có một cú pháp mảng đặc biệt cho chú thích . Danh sách và các bộ sưu tập khác không thể được sử dụng trong các chú thích.

  • Về cách sử dụng, thực hành tốt là thích sử dụng danh sách trên các mảng ở mọi nơi ngoại trừ các phần quan trọng về hiệu năng của mã của bạn, lý do cũng giống như vậy đối với Java .


26

Sự khác biệt chính từ phía sử dụng là Mảng có kích thước cố định trong khi (Mutable)Listcó thể điều chỉnh kích thước của chúng một cách linh hoạt. Hơn nữa Arraylà đột biến trong khi Listkhông.

Hơn nữa, kotlin.collections.Listmột giao diện được thực hiện trong số những người khác bởi java.util.ArrayList. Nó cũng được mở rộng kotlin.collections.MutableListđể sử dụng khi cần một bộ sưu tập cho phép sửa đổi vật phẩm.

Trên cấp độ jvm Arrayđược đại diện bởi các mảng . Listmặt khác được đại diện bởi java.util.Listvì không có bộ sưu tập tương đương có sẵn trong Java.


Tôi không hoàn toàn bị thuyết phục ở đây. Có gì đột biến trong Array? Chỉ có các yếu tố của nó - giống nhau trong List. Kích thước của Listcũng được cố định.
AndroidEx

1
@AndroidEx sau đây sẽ biên dịch val intArray = arrayOf(1,2,3); intArray[0] = 2trong khi điều này sẽ không val intList = listOf(1,2,3); intList[0] = 2. Thực Listtế có một kích thước cố định nhưng MutableListmở rộng nó không có do đó có thể val a:List<Int>sẽ báo cáo khác nhau sizevề các cuộc gọi tiếp theo.
miensol 28/03/2016

Có nên sử dụng Listhay ArrayListkhông?
IgorGanapolsky

2
@IgorGanapolsky Nếu bạn không quan tâm đến việc sử dụng triển khai cụ thể List(có thể là 99% các trường hợp). Nếu bạn quan tâm về việc sử dụng thực hiện ArrayListhoặc LinkedListhoặc bất kỳ thực hiện cụ thể nào khác.
miensol
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.