2013-04-02 33 views
16

Vui lòng kiểm tra nàyscala thêm vào sau một LinkedList có thể thay đổi

import scala.collection.mutable.LinkedList 

var l = new LinkedList[String] 

l append LinkedList("abc", "asd") 

println(l) 
// prints 
// LinkedList() 

nhưng

import scala.collection.mutable.LinkedList 

var l = new LinkedList[String] 

l = LinkedList("x") 
l append LinkedList("abc", "asd") 

println(l) 
// prints 
// LinkedList(x, abc, asd) 

Tại sao hoạt động của đoạn mã thứ hai nhưng một trong những doesnt đầu tiên? Đây là trên Scala 2.10

Trả lời

20

Tài liệu nói If this is empty then it does nothing and returns that. Otherwise, appends that to this.. Đó là chính xác, những gì bạn quan sát thấy. Nếu bạn thực sự cần một danh sách có thể thay đổi, tôi sẽ đề nghị bạn sử dụng scala.collection.mutable.ListBuffer thay vào đó, với nó bạn có thể làm

val lb = new ListBuffer[Int] 

scala> lb += 1 
res14: lb.type = ListBuffer(1) 

scala> lb 
res15: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1) 

scala> lb ++= Seq(1,2,3) 
res17: lb.type = ListBuffer(1, 1, 2, 3, 1, 2, 3) 

scala> lb 
res18: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 1, 2, 3, 1, 2, 3) 
+2

nhưng tại sao lại là hành vi này? tại sao không phụ thuộc vào tự không phân biệt số lượng các phần tử? đây không phải là những gì được mong đợi từ một bộ sưu tập 'mutable'? – weima

+0

Hinestly Tôi không có ý tưởng. Nếu bạn muốn biết lý do chính xác, bạn nên thử danh sách gửi thư chính thức của scala. – drexin

+0

Tôi đoán là vì nó rẻ hơn nhiều so với việc sửa đổi danh sách. Mặc dù, IMHO, mà phá vỡ các hợp đồng ngụ ý rằng các hoạt động đột biến trong thực tế sẽ làm thay đổi danh sách. – dOxxx

3

Theo tôi được biết có liên quan đến Đầu tiên/cuối (Nil) phần tử trong danh sách (nếu danh sách là trống Nil là phần tử đầu tiên và cuối cùng cùng một lúc).

Danh sách liên kết (vẫn) tuân theo chiến lược "primitive charm". Vì vậy, nó không cố gắng thêm/chắp thêm dữ liệu mới vào/sau Nil, để có kết quả khả dĩ như sau: {Nil, newElement}. (Sau khi tất cả Nil nên yếu tố cuối cùng)

Tất nhiên nó có thể kiểm tra danh sách if trống sau đó đặt addingList để bắt đầu và Nil đến cùng. Nhưng điều này sẽ là "quá thông minh", tôi đoán vậy.

Nhưng, dù sao append() lợi nhuận "mong đợi" kết quả Như thế này:

val addingList = new LinkedList[String]("a", "b") 
val result = emptyList append addingList 

result = {"a", "b"}. Trong trường hợp này nó sẽ trả về 'addingList' chính nó, và/nhưng không thay đổi danh sách ban đầu.

Nếu chúng ta cố gắng gán newElement đến next ref:

emptyList.next = LinkedList("whatever") 

Kết quả chúng ta sẽ có emtyList thay đổi như thế này:

LinkedList(null, whatever) 

Tức là nó tạo thành phần tử nắm tay là null, vì chúng tôi đã sử dụng next() gán phần tử mới/tiếp theo cho nó. Vì vậy, nó di chuyển Nil đến cùng, bởi vì phần tử đầu tiên là null, có tham chiếu tiếp đến phần tử mới mà chúng ta đã thêm (addingElelement).

"the "emptyList" cũng là "người đứng đầu" liên kết"

và đầu trong trường hợp đầu của chúng tôi là Nil, nhưng Nill không thể có tiếp theo, vì vậy nó phải tạo phần tử đầu tiên mới (có giá trị null) với tham chiếu next() tới addingElelement mới của chúng tôi.

Cá nhân tôi tìm thấy nó "quá nhiều nguyên thủy" và không "quá nhiều thanh lịch". Nhưng nó phụ thuộc, tôi đoán vậy.

công tác câu chuyện định hướng:

Đối với nhiệm vụ ban đầu của tôi (tại sao tôi bắt đầu suy nghĩ về vấn đề này 'lạ' danh sách hành vi [mặc dù nó có thể thay đổi]) - Tôi muốn sử dụng danh sách có thể thay đổi cho một lớp/đối tượng được gọi là Dictionary sẽ giữ Words trong đó (từ điển theo mặc định không có bất kỳ từ nào). Và tôi sẽ có các phương pháp như một số ddWord(wod:String) để thêm từ mới. Còn bây giờ thực hiện của tôi sẽ được thay đổi (tôi sẽ không sử dụng LinkedList này, nhưng thay vì MutableList Có vẻ như nó là có thể thay đổi nhiều hơn trước một.):

object Dictionary { 

    val words = new mutable.MutableList[Word](); 

    def addWord(word: Word): Unit = { 
    words += word; 
    } 

} 

Nhưng có thể thực hiện có thể là như thế này :

object Dictionary { 

    var words = new mutable.LinkedList[Word](); 

    def addWord(word: Word): Unit = { 

    if (words.isEmpty) { 
     words = words append(mutable.LinkedList[Word](word)) // rely on append result 
    } else { 
     words append(mutable.LinkedList[Word](word)) 
    } 

    } 

} 

Nhưng sau đó tôi phải sử dụng var thay vì val, và tôi nên chuyển đổi tất cả các mới Lời-LinkedList, và logic của tôi trở nên phức tạp hơn.

Các vấn đề liên quan