2011-09-24 28 views
9

Tại sao phiên bản bất biến của cửa hàng ListMap theo thứ tự tăng dần, trong khi các phiên bản có thể thay đổi theo thứ tự giảm dần?Tại sao ListMaps có thể thay đổi và không thay đổi có các đơn đặt hàng khác nhau trong Scala?

Dưới đây là một thử nghiệm mà bạn có thể sử dụng nếu bạn có scalatest-1.6.1.jar và junit-4.9.jar

@Test def StackoverflowQuestion() 
    { 
    val map = Map("A" -> 5, "B" -> 12, "C" -> 2, "D" -> 9, "E" -> 18) 
    val sortedIMMUTABLEMap = collection.immutable.ListMap[String, Int](map.toList.sortBy[Int](_._2): _*) 
    println("head : " + sortedIMMUTABLEMap.head._2) 
    println("last : " + sortedIMMUTABLEMap.last._2) 
    sortedIMMUTABLEMap.foreach(X => println(X)) 
    assert(sortedIMMUTABLEMap.head._2 < sortedIMMUTABLEMap.last._2) 

    val sortedMUTABLEMap = collection.mutable.ListMap[String, Int](map.toList.sortBy[Int](_._2): _*) 
    println("head : " + sortedMUTABLEMap.head._2) 
    println("last : " + sortedMUTABLEMap.last._2) 
    sortedMUTABLEMap.foreach(X => println(X)) 
    assert(sortedMUTABLEMap.head._2 > sortedMUTABLEMap.last._2) 
    } 

Heres đầu ra của thử nghiệm qua:

head : 2 
last : 18 
(C,2) 
(A,5) 
(D,9) 
(B,12) 
(E,18) 
head : 18 
last : 2 
(E,18) 
(B,12) 
(D,9) 
(A,5) 
(C,2) 
+2

một lợi thế lớn của một bộ sưu tập API tốt là nó bảo vệ bạn khỏi phải "triệt tìm hiểu tất cả các sự lập dị như điều này". Thứ tự lặp lại không phải là một phần của hợp đồng của 'ListMap', vì vậy bạn không bao giờ phải suy nghĩ về nó. –

+0

Mô tả giao diện ít cụ thể để lại nhiều không gian hơn cho những thay đổi/cải tiến trong tương lai. Nếu bạn muốn có hành vi đáng tin cậy về thứ tự phần tử, hãy sử dụng 'SortedMap'. – Raphael

+0

Cảm ơn bản đồ đã sắp xếp hoạt động tốt cho tôi. – Zasz

Trả lời

12

Các triệu chứng có thể được đơn giản hóa thành:

scala> collection.mutable.ListMap(1 -> "one", 2 -> "two").foreach(println) 
(2,two) 
(1,one) 

scala> collection.immutable.ListMap(1 -> "one", 2 -> "two").foreach(println) 
(1,one) 
(2,two) 

Việc "sắp xếp" trong mã của bạn không phải là cốt lõi của vấn đề, gọi tới số ListMap đang sử dụng cuộc gọi ListMap.apply từ đối tượng đồng hành xây dựng bản đồ danh sách được hỗ trợ bởi danh sách có thể thay đổi hoặc không thể thay đổi. Quy tắc là thứ tự chèn sẽ được giữ nguyên.

Sự khác biệt có vẻ là danh sách có thể thay đổi được hỗ trợ bởi một danh sách không thay đổi và chèn xảy ra ở phía trước. Vì vậy, đó là lý do tại sao khi lặp lại bạn nhận được hành vi LIFO. Tôi vẫn đang nhìn vào cái không thay đổi nhưng tôi đặt cược những cái chèn có hiệu quả ở phía sau. Chỉnh sửa, tôi đang thay đổi suy nghĩ của tôi: chèn có lẽ là ở phía trước, nhưng có vẻ như phương pháp immutable.ListMap.iterator quyết định đảo ngược kết quả bằng một số toList.reverseIterator trên trình lặp được trả về. Tôi nghĩ rằng nó có giá trị đưa nó vào danh sách gửi thư.

Tài liệu có thể tốt hơn không? Chắc chắn rồi. Có đau không? Không thực sự, tôi không để điều đó xảy ra. Nếu tài liệu không đầy đủ, bạn nên kiểm tra hành vi hoặc tìm kiếm ở nguồn trước khi chọn cấu trúc so với tài liệu khác.

Thực ra, có thể bị đau nếu nhóm Scala quyết định thay đổi hành vi sau này và cảm thấy họ có thể vì hành vi này không có giấy tờ và không có hợp đồng.


Để giải quyết trường hợp sử dụng của bạn được giải thích trong các bình luận, nói rằng bạn đã thu thập được số lượng tần số chuỗi trong một bản đồ (có thể thay đổi hoặc không thay đổi):

val map = Map("A" -> 5, "B" -> 12, "C" -> 2, "D" -> 9, "E" -> 18, "B" -> 5) 

Vì bạn chỉ cần sắp xếp một lần lúc kết thúc, bạn có thể chuyển đổi các bộ từ bản đồ để một seq và sau đó sắp xếp:

map.toSeq.sortBy(_._2) 
// Seq[(java.lang.String, Int)] = ArrayBuffer((C,2), (A,5), (B,5), (D,9), (E,18)) 
+0

Điểm tốt, nó sẽ là một chút của một vấn đề nếu họ thay đổi mọi thứ ngay bây giờ (hoặc sau này). Tôi tìm thấy nó rất khó để gỡ lỗi bởi vì kiểm tra sắp xếp và nguồn của tôi đã có cùng một mã chính xác, nhưng các phiên bản khác nhau của ListMap. Sẽ tốt hơn nếu các bộ sưu tập có tên tốt hơn đại diện cho khả năng biến đổi của chúng – Zasz

+0

Tôi sẽ đánh dấu câu trả lời này là chính xác nếu bạn có thể đề xuất cấu trúc dữ liệu nào tôi nên sử dụng, tôi cần sắp xếp các cặp (chuỗi, int) được sắp xếp theo giá trị int và CÓ THỂ sau khi sắp xếp. – Zasz

+0

@Zasz, bạn có cho phép trùng lặp hoặc nhiều chuỗi cho cùng một int trong bảng của mình không? Bạn có cần bàn để được sắp xếp khi nó bị đột biến không? Hoặc nó là tốt nếu bạn sắp xếp nó trước khi hiển thị/lặp? Tôi sẽ không chấp nhận câu trả lời của tôi cho đến khi tôi nghe lại từ danh sách gửi thư ... – huynhjl

4

Như tôi đã nhìn thấy nó không ListMap tuyên bố là một chỉ là một bản đồ bản đồ được sắp xếp, được triển khai với Danh sách. Trong thực tế, tôi không thấy bất cứ điều gì trong hợp đồng của họ mà nói bất cứ điều gì về việc bảo quản thứ tự chèn.

Lập trình trong Scala giải thích rằng ListMap có thể được sử dụng nếu các phần tử đầu tiên có nhiều khả năng được truy cập, nhưng nếu không thì nó có ít lợi thế hơn Bản đồ.

+1

Chính xác những gì tôi có ý nghĩa về không đủ thông tin về cấu trúc dữ liệu. Làm thế nào tôi đã kết thúc việc lựa chọn ListMap là sau khi nhìn thấy một thread trong stackoverflow, mà sử dụng nó để phân loại. Và dựa trên những gì được viết cho tài liệu ListMap, rất khó để biết được nơi sử dụng ListMap – Zasz

1

Không xây dựng bất kỳ kỳ vọng nào theo thứ tự, nó không được khai báo và sẽ khác nhau giữa các phiên bản Scala.

Ví dụ:

import scala.collection.mutable.{ListMap => MutableListMap} 

MutableListMap("A" -> 5, "B" -> 12, "C" -> 2, "D" -> 9, "E" -> 18).foreach(println) 

On 2.9.1 cho: (E, 18) (D, 9) (C, 2) (B, 12) (A, 5)

nhưng trên 2.11.6 cho: (E, 18) (C, 2) (A, 5) (B, 12) (D, 9)

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