2009-01-30 12 views
100

में मैं कुछ स्काला कोड जो Apache POI API का उपयोग करता लिख ​​रहा हूँ। मैं java.util.Iterator में निहित पंक्तियों पर फिर से शुरू करना चाहता हूं जो मुझे शीट क्लास से मिलता है। मैं इटरेटर को for each स्टाइल लूप में उपयोग करना चाहता हूं, इसलिए मैं इसे मूल स्कैला संग्रह में बदलने की कोशिश कर रहा हूं लेकिन कोई भाग्य नहीं होगा।पुनरावृत्ति जावा से अधिक संग्रह स्काला

मैंने स्कैला रैपर कक्षाओं/लक्षणों को देखा है, लेकिन मैं नहीं देख सकता कि उन्हें सही तरीके से कैसे उपयोग किया जाए। मैं verbose while(hasNext()) getNext() लूप की शैली का उपयोग किए बिना स्कैला में जावा संग्रह पर कैसे पुन: प्रयास करूं?

class IteratorWrapper[A](iter:java.util.Iterator[A]) 
{ 
    def foreach(f: A => Unit): Unit = { 
     while(iter.hasNext){ 
      f(iter.next) 
     } 
    } 
} 

object SpreadsheetParser extends Application 
{ 
    implicit def iteratorToWrapper[T](iter:java.util.Iterator[T]):IteratorWrapper[T] = new IteratorWrapper[T](iter) 

    override def main(args:Array[String]):Unit = 
    { 
     val ios = new FileInputStream("assets/data.xls") 
     val workbook = new HSSFWorkbook(ios) 
     var sheet = workbook.getSheetAt(0) 
     var rows = sheet.rowIterator() 

     for (val row <- rows){ 
      println(row) 
     } 
    } 
} 
+0

मैं (वैल पंक्ति के लिए लाइन "शामिल करने के लिए नहीं कर पा रहे <- पंक्तियां) {"पार्सर सोचने के बिना '<' वर्ण एक एक्सएमएल समापन टैग है? बैकटिक्स –

+0

काम नहीं करते हैं, आपको इटरैटिरवापर में निहित रूप से परिवर्तित करने में सक्षम होना चाहिए, जिससे आप सिंटैक्स का एक उचित हिस्सा बचा सकते हैं। स्कैला में निहित रूपांतरण के लिए Google। –

उत्तर

25

एक आवरण वर्ग नहीं है (scala.collection.jcl.MutableIterator.Wrapper)। तो अगर आप

implicit def javaIteratorToScalaIterator[A](it : java.util.Iterator[A]) = new Wrapper(it) 

को परिभाषित तो यह स्काला इटरेटर की एक उप वर्ग के रूप में कार्य करें ताकि आप foreach कर सकते हैं होगा।

+0

इसे पढ़ना चाहिए: scala.collection.jcl.MutableIterator.Wrapper – samg

+33

यह उत्तर स्कैला 2.8 में अप्रचलित है; http://stackoverflow.com/questions/2708990/whats-the-new-way-to-iterate-over-a-java-map-in-scala-2-8-0 –

15

सही जवाब यहाँ जावा के Iterator कुछ कस्टम प्रकार से एक अंतर्निहित रूपांतरण परिभाषित करने के लिए है:

यहाँ कोड मैं सही जवाब के आधार पर लिखा है। इस प्रकार को foreach विधि लागू करना चाहिए जो अंतर्निहित Iterator पर प्रतिनिधि है। यह आपको किसी भी जावा Iterator के साथ स्कैला for -loop का उपयोग करने की अनुमति देगा।

4

आप एक सरणी के लिए जावा संग्रह परिवर्तित कर सकते हैं और उस का उपयोग करें:

val array = java.util.Arrays.asList("one","two","three").toArray 
array.foreach(println) 

या पर जाने के लिए और एक स्काला सूची में सरणी परिवर्तित:

val list = List.fromArray(array) 
237

स्कैला 2.8 के अनुसार, आपको केवल जावा कॉन्फ़्रेंस ऑब्जेक्ट आयात करना है, जो पहले से ही उचित रूपांतरण घोषित करता है।

import scala.collection.JavaConversions._ 

हालांकि यह पिछले संस्करणों में काम नहीं करेगा।

9

स्काला 2.10 के लिए:

// Feature warning if you don't enable implicit conversions... 
import scala.language.implicitConversions 
import scala.collection.convert.WrapAsScala.enumerationAsScalaIterator 
5
स्काला के साथ

2.10.4+ (और संभवतः पहले) यह संभव है परोक्ष कन्वर्ट करने के लिए java.util.Iterator [एक] scala.collection.Iterator को [एक] द्वारा scala.collection.JavaConversions.asScalaIterator आयात करना। यहाँ एक उदाहरण है:

object SpreadSheetParser2 extends App { 

    import org.apache.poi.hssf.usermodel.HSSFWorkbook 
    import java.io.FileInputStream 
    import scala.collection.JavaConversions.asScalaIterator 

    val ios = new FileInputStream("data.xls") 
    val workbook = new HSSFWorkbook(ios) 
    var sheet = workbook.getSheetAt(0) 
    val rows = sheet.rowIterator() 

    for (row <- rows) { 
    val cells = row.cellIterator() 
    for (cell <- cells) { 
     print(cell + ",") 
    } 
    println 
    } 

} 
2

आप scala.collection.JavaConversions में implicits से बचने के लिए आप scala.collection.JavaConverters उपयोग कर सकते हैं स्पष्ट रूप से परिवर्तित करने के लिए चाहते हैं, तो।

scala> val l = new java.util.LinkedList[Int]() 
l: java.util.LinkedList[Int] = [] 

scala> (1 to 10).foreach(l.add(_)) 

scala> val i = l.iterator 
i: java.util.Iterator[Int] = [email protected] 

scala> import scala.collection.JavaConverters._ 
import scala.collection.JavaConverters._ 

scala> i.asScala.mkString 
res10: String = 12345678910 

नोट asScala विधि का उपयोग एक स्काला Iterator जावा Iterator कन्वर्ट करने के लिए।

जावाकॉन्टर स्केल 2.8.1 के बाद उपलब्ध हैं।

+0

मैंने 'आयात scala.collection' का उपयोग किया .JavaConverters._' और फिर 'javaList.iterator()। AsScala' आपके उदाहरण से और यह काम करता है –

1

यदि आप एक बड़े डेटासेट के माध्यम से पुनरावृत्त कर रहे हैं, तो संभवतः आप .asScala अंतर्निहित रूपांतरण के साथ पूरे संग्रह को स्मृति में लोड नहीं करना चाहते हैं।इस मामले में, एक आसान तरीका दृष्टिकोण scala.collection.Iterator विशेषता

import java.util.{Iterator => JIterator} 

def scalaIterator[T](it: JIterator[T]) = new Iterator[T] { 
    override def hasNext = it.hasNext 
    override def next() = it.next() 
} 

val jIterator: Iterator[String] = ... // iterating over a large dataset 
scalaIterator(jIterator).take(2).map(_.length).foreach(println) // only first 2 elements are loaded to memory 

यह समान अवधारणा लेकिन के 2.12.0 एक ही रास्ता के बाद से कर रही है कम वर्बोज़ IMO :)

4

स्काला 2.12.0 scala.collection.JavaConversions deprecates, इसलिए लागू करने के लिए है इस होगा कुछ की तरह:

import scala.collection.JavaConverters._ 

// ... 

for(k <- javaCollection.asScala) { 
    // ... 
} 

(आयात नोटिस, नई JavaConverters, बहिष्कृत है JavaConversions है)