2011-09-28 9 views
13

Xin vui lòng chịu với tôi, tôi vẫn còn khá noobish với Scala. Tôi có đoạn mã sau:java.util.Iterator đến danh sách Scala?

private lazy val keys : List[String] = obj.getKeys().asScala.toList 

obj.getKeys trả về một java.util.Iterator

Calling asScala, qua JavaConverers (được nhập khẩu) theo các tài liệu ..

java.util.Iterator <==> scala.collection.Iterator 

scala.collection.Iterator định nghĩa

def toList : List[A] 

Vì vậy, dựa trên điều này tôi tin rằng điều này sẽ hoạt động, howev er ở đây là lỗi biên dịch.

[scalac] <file>.scala:11: error: type mismatch; 
[scalac] found : List[?0] where type ?0 
[scalac] required: List[String] 
[scalac] private lazy val keys : List[String] = obj.getKeys().asScala.toList 
[scalac] one error found 

Tôi hiểu tham số kiểu hoặc Iterator java là một chuỗi Java, và tôi đang cố gắng để tạo ra một danh sách các chuỗi Scala, nhưng (có lẽ ngây thơ) nghĩ rằng sẽ có một sự chuyển đổi ngầm.

Trả lời

10

Điều đó sẽ hiệu quả nếu obj.getKeys() là java.util.Iterator<String>. Tôi cho là không.

Nếu obj.getKeys() chỉ java.util.Iterator ở dạng thô, không java.util.Iterator<String>, thậm chí không java.util.Iterator<?> là, đây là một cái gì đó scala có xu hướng không thích, nhưng dù sao, không có cách nào scala sẽ gõ biểu hiện của bạn như List[String] nếu nó không có bảo đảm obj.getKeys() chứa chuỗi .

Nếu bạn biết iterator của bạn nằm trên Strings, nhưng loại không nói như vậy, bạn có thể đúc:

obj.getKeys().asInstanceOf[java.util.Iterator[String]] 

(sau đó đi về với .asScala.toList)

Lưu ý rằng, cũng giống như trong java và do loại xóa, dàn diễn viên đó sẽ không được kiểm tra (bạn sẽ nhận được cảnh báo). Nếu bạn muốn kiểm tra ngay lập tức mà bạn có Strings, bạn thay vì có thể làm

obj.getKeys().map(_.asInstanceOf[String]) 

mà sẽ kiểm tra kiểu của mỗi yếu tố trong khi bạn lặp để xây dựng danh sách

+1

Cảm ơn rất nhiều vì câu trả lời! có vẻ như bạn và Matthew Farwell đồng ý cho hầu hết các phần. Tôi đã làm những gì bạn đề nghị, obj.getKeys(). AsInstanceOf [java.util.Iterator [String]]. AsScala.toList và dường như làm việc, và tôi đã không nhận được một cảnh báo biên dịch. – rshepherd

24

Bạn không cần phải gọi asScala, nó là một chuyển đổi ngầm:

import scala.collection.JavaConversions._ 

val javaList = new java.util.LinkedList[String]() // as an example 

val scalaList = javaList.iterator.toList 

Nếu bạn thực sự không có tham số kiểu của iterator, chỉ cần bỏ nó vào đúng loại:

javaList.iterator.asInstanceOf[java.util.Iterator[String]].toList 

EDIT: Một số người không muốn sử dụng chuyển đổi ngầm trong JavaConversions, nhưng sử dụng trình trang trí asScala/asJava trong JavaConverters để làm cho chuyển đổi rõ ràng hơn.

+0

Bạn nói đúng, không có tham số kiểu cho Iterator đang được trả về từ phương thức getKeys(). Quan sát rất sắc sảo, cảm ơn bạn. Mặc dù nó xuất hiện tôi cần asScala trong đó, trong trường hợp đó. Có lẽ có cái gì đó khác tôi đang mất tích. – rshepherd

+0

Chuyển đổi ngầm định nằm trên 'JavaConversions', nhưng không phải trên' JavaConverters'. Điều đó sử dụng 'asScala'. Nhiều người, bao gồm cả bản thân tôi, thích thực hiện chuyển đổi này rõ ràng hơn để tránh các lỗi tinh vi. –

+0

@Daniel Tôi đoán việc tạo nội dung rõ ràng là một ý tưởng hay, cảm ơn mẹo. –

3

Tôi không thích những câu trả lời khác. Địa ngục, tôi không thích bất cứ điều gì gợi ý sử dụng asInstanceOf trừ khi không có thay thế. Trong trường hợp này, có. Nếu bạn thực hiện việc này:

private lazy val keys : List[String] = obj.getKeys().asScala.collect { 
    case s: String => s 
}.toList 

Bạn xoay Iterator[_] thành Iterator[String] một cách an toàn và hiệu quả.