Danh sách của Kotlin bị thiếu các ứng dụng khác, thêm vào đó


197

Trong Java, chúng ta có thể làm như sau

public class TempClass {
    List<Integer> myList = null;
    void doSomething() {
        myList = new ArrayList<>();
        myList.add(10);
        myList.remove(10);
    }
}

Nhưng nếu chúng ta viết lại nó cho Kotlin trực tiếp như dưới đây

class TempClass {
    var myList: List<Int>? = null
    fun doSomething() {
        myList = ArrayList<Int>()
        myList!!.add(10)
        myList!!.remove(10)
    }
}

Tôi đã gặp lỗi không tìm thấy addremovehoạt động từ Danh sách của tôi

Tôi làm việc xung quanh việc chuyển nó thành ArrayList, nhưng đó là điều cần thiết để truyền nó, trong khi trong quá trình truyền Java thì không bắt buộc. Và điều đó đánh bại mục đích có Danh sách lớp trừu tượng

class TempClass {
    var myList: List<Int>? = null
    fun doSomething() {
        myList = ArrayList<Int>()
        (myList!! as ArrayList).add(10)
        (myList!! as ArrayList).remove(10)
    }
}

Có cách nào để tôi sử dụng Danh sách nhưng không cần phải sử dụng Danh sách, như những gì có thể được thực hiện trong Java không?


1
Chỉ cần một nhận xét về lý do tại sao bạn không thể làm myList = nullvà sau đó trong cuộc gọi thêm mà không có !!. Bạn có thể khắc phục điều này bằng cách sử dụng lateinittừ khóa trước tài sản của mình như vậy: lateinit var myList: List<Int>theo cách này bạn sẽ không cần phải khởi tạo danh sách ngay lập tức, nhưng bạn đảm bảo với trình biên dịch rằng bạn sẽ khởi tạo nó trước khi sử dụng danh sách lần đầu tiên. Đó là một giải pháp mượt mà hơn, nhưng nó đặt trách nhiệm cho bạn với tư cách là một nhà phát triển.
Darwind

Câu trả lời:


351

Không giống như nhiều ngôn ngữ, Kotlin phân biệt giữa các bộ sưu tập có thể thay đổi và bất biến (danh sách, bộ, bản đồ, v.v.). Kiểm soát chính xác khi chính xác các bộ sưu tập có thể được chỉnh sửa là hữu ích để loại bỏ lỗi và để thiết kế các API tốt.

https://kotlinlang.org/docs/reference/collections.html

Bạn sẽ cần sử dụng một MutableListdanh sách.

class TempClass {
    var myList: MutableList<Int> = mutableListOf<Int>()
    fun doSomething() {
        // myList = ArrayList<Int>() // initializer is redundant
        myList.add(10)
        myList.remove(10)
    }
}

MutableList<Int> = arrayListOf() cũng nên làm việc


4
Câu trả lời hay và được viết tốt. Tôi đang chọn câu trả lời của người mẫu mặc dù có câu trả lời của tôi bên dưới :)
Elye

6
Bạn không cần phải làm cho danh sách trở nên vô hiệu nếu bạn khởi tạo nó ngay lập tức. Tôi chỉnh sửa câu trả lời của bạn.
Kirill Rakhman

37

Xác định bộ sưu tập Danh sách trong Kotlin theo các cách khác nhau:

  • Biến bất biến với danh sách bất biến (chỉ đọc):

    val users: List<User> = listOf( User("Tom", 32), User("John", 64) )


  • Biến bất biến với danh sách đột biến:

    val users: MutableList<User> = mutableListOf( User("Tom", 32), User("John", 64) )

    hoặc không có giá trị ban đầu - danh sách trống và không có loại biến rõ ràng:

    val users = mutableListOf<User>()
    //or
    val users = ArrayList<User>()
    • bạn có thể thêm các mục vào danh sách:
      • users.add(anohterUser) hoặc là
      • users += anotherUser(dưới mui xe nó users.add(anohterUser))


  • Biến có thể thay đổi với danh sách bất biến:

    var users: List<User> = listOf( User("Tom", 32), User("John", 64) )

    hoặc không có giá trị ban đầu - danh sách trống và không có loại biến rõ ràng:

    var users = emptyList<User>()
    • LƯU Ý: bạn có thể thêm * mục vào danh sách:
      • users += anotherUser - * nó tạo ArrayList mới và gán nó cho users


  • Biến có thể thay đổi với danh sách có thể thay đổi:

    var users: MutableList<User> = mutableListOf( User("Tom", 32), User("John", 64) )

    hoặc không có giá trị ban đầu - danh sách trống và không có loại biến rõ ràng:

    var users = emptyList<User>().toMutableList()
    //or
    var users = ArrayList<User>()
    • LƯU Ý: bạn có thể thêm các mục vào danh sách:
      • users.add(anohterUser)
      • nhưng không sử dụng users += anotherUser

        Lỗi: Kotlin: Chuyển nhượng toán tử mơ hồ:
        toán tử công khai fun Collection.plus (phần tử: Chuỗi): Danh sách được xác định trong kotlin.collections
        @InlineOnly toán tử nội tuyến công khai vui vẻ MutableCollection.plusAssign (phần tử: Chuỗi): Đơn vị được xác định trong kotlin.collections


xem thêm: https://kotlinlang.org/docs/reference/collections.html


9

Đồng ý với tất cả các câu trả lời ở trên về việc sử dụng MutableList nhưng bạn cũng có thể thêm / xóa khỏi Danh sách và nhận danh sách mới như bên dưới.

val newListWithElement = existingList + listOf(element)
val newListMinusElement = existingList - listOf(element)

Hoặc là

val newListWithElement = existingList.plus(element)
val newListMinusElement = existingList.minus(element)

8

Rõ ràng, Danh sách mặc định của Kotlin là bất biến. Để có một Danh sách có thể thay đổi, người ta nên sử dụng MutableList như bên dưới

class TempClass {
    var myList: MutableList<Int>? = null
    fun doSomething() {
        myList = ArrayList<Int>()
        myList!!.add(10)
        myList!!.remove(10)
    }
}

Tuy nhiên, đã cập nhật , không nên sử dụng MutableList trừ khi có danh sách mà bạn thực sự muốn thay đổi. Đề cập đến https://hackernoon.com/read-only-collection-in-kotlin-leads-to-better-coding-40cdfa4c6359 về cách bộ sưu tập Chỉ đọc cung cấp mã hóa tốt hơn.


Bạn đã đúng về việc sử dụng MutableList, tuy nhiên việc khởi tạo nó nullsẽ không hiệu quả. Chỉ các cuộc gọi được xác nhận an toàn hoặc không null mới được phép trên một loại máy thu không thể loại được MutableList<Int>.
Fulvio

Nó hoạt động vào cuối của tôi, và không tìm thấy lỗi. Tôi không cần phải khởi tạo nó trừ khi tôi cần nó khidoSomething
Elye

@Elye Tôi biết đây là một câu trả lời và câu hỏi cũ, nhưng sử dụng lateinitthay vì làm cho danh sách trở nên vô giá trị là cách thích hợp để giải quyết vấn đề này. lateinitMặc dù vậy, đừng nhớ liệu đã được thêm từ đầu của Kotlin hay chưa, nhưng đây chắc chắn là giải pháp hiện nay để sử dụng nó :-)
Darwind

5

Trong Kotlin bạn phải sử dụng MutableListhoặc ArrayList.

Chúng ta hãy xem các phương pháp MutableListlàm việc:

var listNumbers: MutableList<Int> = mutableListOf(10, 15, 20)
// Result: 10, 15, 20

listNumbers.add(1000)
// Result: 10, 15, 20, 1000

listNumbers.add(1, 250)
// Result: 10, 250, 15, 20, 1000

listNumbers.removeAt(0)
// Result: 250, 15, 20, 1000

listNumbers.remove(20)
// Result: 250, 15, 1000

for (i in listNumbers) { 
    println(i) 
}

Chúng ta hãy xem các phương pháp ArrayListlàm việc:

var arrayNumbers: ArrayList<Int> = arrayListOf(1, 2, 3, 4, 5)
// Result: 1, 2, 3, 4, 5

arrayNumbers.add(20)
// Result: 1, 2, 3, 4, 5, 20

arrayNumbers.remove(1)
// Result: 2, 3, 4, 5, 20

arrayNumbers.clear()
// Result: Empty

for (j in arrayNumbers) { 
    println(j) 
}

4

Bạn có thể làm với việc tạo một cái mới như thế này.

var list1 = ArrayList<Int>()
var list2  = list1.toMutableList()
list2.add(item)

Bây giờ bạn có thể sử dụng list2, Cảm ơn bạn.



2

Hạn chế khả năng tương tác với các nhà xây dựng

Các câu trả lời hàng đầu ở đây nói chính xác về sự khác biệt trong Kotlin giữa chỉ đọc List(LƯU Ý: đó là chỉ đọc, không "bất biến" ) và MutableList.

Nói chung, người ta nên cố gắng sử dụng các danh sách chỉ đọc, tuy nhiên, tính dễ biến đổi vẫn thường hữu ích khi xây dựng , đặc biệt là khi làm việc với các thư viện của bên thứ ba với giao diện không có chức năng. Đối với các trường hợp không có sẵn các kỹ thuật xây dựng thay thế, chẳng hạn như sử dụng listOftrực tiếp hoặc áp dụng một cấu trúc chức năng như foldhoặc reduce, một cấu trúc "hàm xây dựng" đơn giản như sau đây sẽ tạo ra một danh sách chỉ đọc từ một biến đổi tạm thời:

val readonlyList = mutableListOf<...>().apply {
  // manipulate your list here using whatever logic you need
  // the `apply` function sets `this` to the `MutableList`
  add(foo1)
  addAll(foos)
  // etc.
}.toList()

và điều này có thể được gói gọn trong một chức năng tiện ích nội tuyến có thể sử dụng lại:

inline fun <T> buildList(block: MutableList<T>.() -> Unit) = 
  mutableListOf<T>().apply(block).toList()

có thể được gọi như thế này:

val readonlyList = buildList<String> {
  add("foo")
  add("bar")
}

Bây giờ, tất cả các khả năng biến đổi được tách biệt thành một phạm vi khối được sử dụng để xây dựng danh sách chỉ đọc và phần còn lại của mã của bạn sử dụng danh sách chỉ đọc được xuất ra từ trình xây dựng.

CẬP NHẬT : Kể từ Kotlin 1.3,70, buildListhàm chính xác ở trên có sẵn trong thư viện chuẩn dưới dạng hàm thử nghiệm, cùng với các chất tương tự buildSetbuildMap. Xem https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-3-70-release/ .


cảm ơn và làm việc tốt với logic nghiệp vụ trong phương thức áp dụng, thậm chí đã sử dụng một ListList.ForEach {add (foo)} bên trong .appy {}
BENN1TH

1

Trong khái niệm dữ liệu bất biến, có lẽ đây là một cách tốt hơn:

class TempClass {
    val list: List<Int> by lazy {
        listOf<Int>()
    }
    fun doSomething() {
        list += 10
        list -= 10
    }
}

1

A listimmutablebởi Default, bạn có thể sử dụng ArrayListthay thế. như thế này :

 val orders = arrayListOf<String>()

sau đó bạn có thể add/deletecác mục từ này như dưới đây:

orders.add("Item 1")
orders.add("Item 2")

theo mặc định ArrayListmutableđể bạn có thể thực hiện các thao tác trên nó.

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.