List
EinstiegEine
List erzeugenElementzugriff
Methoden der Klasse
ListEinstieg
Die Klasse scala.collection.immutable.List ist eine der am meist verwendeten Datenstrukturen
in Scala. Es handelt sich dabei um eine sequenzielle
Liste eines bestimmten Datentyps. Dementsprechend enthält eine List[Double]
nur Elemente vom Datentyp Double.
Da List eine unveränderliche Datenstruktur ist, können die enthaltenen Elemente
nicht verändert werden.
Der "Zustand" eines enthaltenen Elementes kann evtl. doch verändert werden,
da sich die Unveränderbarkeit nur auf die enthaltenen Referenzen, jedoch nicht auf
die in den Referenzen enthaltenen Elemente, bezieht.
Die API-Dokumentation der Klasse List finden wir unter
http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.List
Eine List erzeugen
Da es sich bei der Klasse scala.collection.immutable.List um eine abstrakte Klasse
handelt, können wir eine List nicht mit dem Schlüsselwort new
instanziieren. Eine Möglichkeit ist die Verwendung der Methode apply aus dem
Begleitobjekt
der Klasse List zu verwenden. Die Methode apply dient hier als Factory-Methode
zur Erzeugung von Objekten des Typs List.
scala> val list : List[Int] = List.apply(2,1,3) list: List[Int] = List(2, 1, 3)timpt.de - X2H V 0.11
Die Syntax von Scala erlaubt es die Angabe des Methodennamens apply
wegzulassen, wenn direkt hinter dem Klassennamen die Runden Klammern angegeben werden.
Da auch der Typparameter vom Compiler abgeleitet werden kann, ist die Erzeugung
obiger Liste auch mit folgender Syntax möglich:
scala> val list = List(2,1,3) list: List[Int] = List(2, 1, 3)timpt.de - X2H V 0.11
Eine weitere Möglichkeit eine List zu erzeugen ist
die Methode :: der Klasse List. :: wird
auch mit dem Namen "cons" bezeichnet. In der Operatorschreibweise
kommt auch "Cons-Operator" als Bezeichnung vor.
Da ::
eine Methode der Klasse List ist, kann die neue List
nur auf Basis einer bestehenden List erzeugt werden.
Ist keine List als Basis vorhanden, kann Nil,
welches eine leere List repräsentiert, verwendet werden.
In der Operatorschreibweise wird die Ausgangs-List am Ende
des gesamten Ausdrucks angegeben. Dem ist so, da der "Cons-Operator"
auf einem Doppelpunkt endet und somit die Methode auf dem rechten Operanden
ausgeführt wird.
scala> val list = 2 :: 1 :: 3 :: Nil list: List[Int] = List(2, 1, 3)timpt.de - X2H V 0.11
Elementzugriff
Nachdem wir nun wissen, wie wir eine List erzeugen können, ist es nun an der Zeit
herauszufinden, wie wir wieder Zugriff auf die Elemente erhalten. Auch hier hilft uns wieder die
Methode apply, aber diesmal aus der Begleitklasse.
Die Methode apply erwartet hier den Index des gewünschten Objektes.
Die Indizierung der Elemente erfolgt beginnend mit 0. Um also auf das zweite Element einer
List zuzugreifen, verwenden wir als Index 1. Nachfolgend ein REPL Beispiel,
wo eine List erzeugt wird und anschließend auf das zweite Element zugegriffen wird.
scala> val myList = List(2,11,33,22) myList: List[Int] = List(2, 11, 33, 22) scala> println(myList.apply(1)) 11timpt.de - X2H V 0.11
Auch hier erlaubt uns die Scala Syntax, die Angabe des Methodennamens apply wegzulassen.
Wir können direkt nach dem Objektnamen den Index des gewünschten Elements (hier das dritte Element) in runden Klammern angegeben.
scala> println(myList(2)) 33timpt.de - X2H V 0.11
Methoden der Klasse List
Für die Klasse List sind eine Fülle nützlicher Methoden definiert.
Viele der beschriebenen Methoden / Funktionen sind nicht ausschließlich für die Klasse
oder in der Klasse List definiert.
Auch wenn es anders erscheint, wird keine List durch den Aufruf einer Methode
verändert. Würde eine List durch eine Methode verändert, würde
es sich bei einer List nicht um einen unveränderlichen Datentyp
handeln. Nachfolgend sollen ausgewählte Methoden der Klasse List
vorgestellt werden.
++ |
Verbindet eine List mit den Elementen einer traversablen Collection.
|
+: |
Erzeugt eine neue List bestehend aus einem hinzuzufügendem
Element, gefolgt von der Ausgangsliste.
|
| :: |
Erzeugt eine List bestehnd aus einem neuen Element und einer
List.
|
::: |
Verbindet zwei List Objekte zu einer neuen List.
|
contains |
Überprüft, ob ein Element in der Liste enthalten ist. |
drop
|
Erzeugt eine neue List mit den Elementen der Ursprungsliste,
ohne die ersten, im Parameter angegebenen, n Elemente.
|
dropRight
|
Erzeugt eine neue List mit den Elementen der Ursprungsliste,
ohne die letzten, im Parameter angegebenen, n Elemente.
|
exists
|
Überprüft, ob zumindest ein Element der Liste die Anforderung der übergebenen Funktion entspricht. |
filter |
Erzeugt eine Liste bestehend aus Elementen der Ausgangsliste, die eine zu definierende Bedinung erfüllen. |
foreach |
foreach liefert nacheinander die Elemente der Liste, auf die
foreach aufgerufen wird.
|
head |
Liefert das erste Element der List.
|
length |
Liefert die Anzahl Elemente in der List | .
map |
Erzeugt eine neue Liste durch Anwendung einer Funktion auf alle Elemente der Ausgangsliste |
reduceLeft |
Iteriert paarweise über die Liste und wertet die übergebene Funktion auf die übergebenen Parameter aus. |
reverse: List[A] |
Liefert eine List mit allen Elementen der Ursprungsliste,
wobei die Elemente in umgekehrter Reihenfolge enthalten sind.
|
size |
Liefert die Anzahl Elemente in der List (entspricht length).
|
tail |
Liefert eine neue List, ohne das erste Element der List
auf dem tail aufgerufen wurde.
|
++
def ++ [B] (that: GenTraversableOnce[B]): List[B]
def ++ [B >: A, That] (that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That
def ++ [B >: A, That] (that: TraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That
Mit ++ wird auf Basis einer List eine neue List erzeugt,
die aus den Elementen der List besteht und aus den Elementen der als Parameter
übergebenen traversablen Collection.
Das nachfolgende Beispiel zeigt die Erzeugung einer List aus einer List
und einem Array.
object PlusPlus {
def main(args: Array[String]) {
val list = List(1,2,3,4,5)
val array = Array(6,7,8,9)
val list2 = list ++ array
println(list2)
}
}
timpt.de - X2H V 0.11
Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:
List(1, 2, 3, 4, 5, 6, 7, 8, 9)
+:
Erzeugt eine neue List bestehend aus einem hinzuzufügendem
Element, gefolgt von der Ausgangsliste.
def +: (elem: A): List[A]
def +: [B >: A, That] (elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That
object PrependIt {
def main(args: Array[String]) {
val list = List(1,2,3,4)
val list2 = 5 +: list
println(list2)
}
}
timpt.de - X2H V 0.10
Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:
List(5, 1, 2, 3, 4)
::
def :: (x: A) : List[A]
def :: [B >: A] (x: B): List[B]
Die Methode :: erzeugt eine neue List bestehend
aus dem in der Methode übergebenem Argumentes gefolgt vom Inhalt
der Liste auf der :: aufgerufen wurde.
Nachfolgend ein Skript Beispiel zur Methode :: in Punkt-Schreibweise.
val list1 = List(2,3,4) val list2 = list1.::(1) println(list1) println(list2)timpt.de - X2H V 0.7
Die Ausführung dieses Skriptes führt zur folgenden Ausgabe auf der Systemausgabe:
List(2, 3, 4)
List(1, 2, 3, 4)
Wie bei der Methode ::: ist bei der Methode :: die
Operator-Schreibweise geläufiger. Da der Methodenname mit einem Doppelpunkt
endet, wird diese bei der Operator-Schreibweise auf den rechten Operanden
mit dem linken Operanden als Argument aufgerufen.
Das nachfolgende Skript entspricht dem obigen in Operator-Schreibweise und führt bei dessen Ausgabe zum gleichen Ergebnis.
val list1 = List(2,3,4) val list2 = 1 :: list1 println(list1) println(list2)timpt.de - X2H V 0.7
Die Methode :: eignet sich auch dazu einzelne Elemente
zu einer Liste zu verbinden. Das nachfolgende Skript zeigt exemplarisch
diese Vorgehensweise.
val list1 = 1 :: 2 :: 3 :: 4 :: Nil println(list1)timpt.de - X2H V 0.7
Die Ausführung dieses Skriptes führt zu folgender Ausgabe:
List(1, 2, 3, 4)
Da die Methode :: in der Klasse List definiert
ist, muss als letztes Element ein List Objekt angegeben werden,
worauf die Methode :: aufgerufen wird. In unserem Beispiel
ist dies Nil, was einer leeren List entspricht.
:::
def ::: (prefix: List[A]) : List[A]
def ::: [B >: A] (prefix: List[B]) : List[B]
Die Methode ::: verbindet zwei Listen zu einer neuen List. Die Ergebnisliste
beginnt dabei mit den Elementen, die als Argument der Methode übergeben wurde, gefolgt
von den Elementen der Liste auf der die Methode ::: aufgerufen wurde.
Im nachfolgendem Skript werden zunächst zwei Listen den Variablen
list1 und list2 zugewiesen. Anschließend
wird eine neue Liste mit dem Inhalt von list1 und list2
erstellt und der Variablen list3 zugewiesen.
val list1 = List(1,2,3) val list2 = List(4,5,6) val list3 = list2.:::(list1) println(list1) println(list2) println(list3)timpt.de - X2H V 0.7
Die Ausführung des Skriptes führt zu folgender Ausgabe:
List(1, 2, 3)
List(4, 5, 6)
List(1, 2, 3, 4, 5, 6)
Die Verwendung der Methode ::: in der Schreibweise mit Punkt und Klammern
wird man in der Praxis weniger häufig antreffen. Geläufiger ist die Operator - Schreibweise.
Da die Methode mit einem Doppelpunkt endet, wird die Methode auf den rechten Operanden
ausgeführt. Dies erhöht deutlich die Lesbarkeit, da die Elemente des linken
Operanden vor den Elementen des rechten Operanden im Ergebnis erscheinen.
Das nachfolgende Beispiel entspricht dem obigem Beispiel, mit Ausnahme, das hier die Operator-Schreibweise angewendet wird.
val list1 = List(1,2,3) val list2 = List(4,5,6) val list3 = list1 ::: list2 println(list1) println(list2) println(list3)timpt.de - X2H V 0.4
contains
def contains (elem: Any): Boolean
Die Funktion contains überprüft ob ein übergebenes Element in der
Liste enthalten ist. Nachfolgend eine beispielhafte Anwendung:
object ContainsIt {
def main(args: Array[String]){
val myList = List("123","abc","456","def")
println(myList contains "1234")
println(myList contains "abc")
}
}
timpt.de - X2H V 0.11
Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:
false
true
exists
def exists (p: (A) => Boolean): Boolean
Die Funktion exists überprüft, ob zumindest ein Element der Liste die Anforderung der übergebenen Funktion entspricht.
Im nachfolgenden Beispiel werden zwei List Objekte mit Int Werten erzeugt. Die Variable myFunction ist
einer Funktion zugeordnet, die als Parameter einen Int-Wert erwartet und als Ergebnis true liefert, wenn
das Argument durch 2 ohne Rest teilbar ist. Diese Funktion übergeben wir der Funktion exists der zuvor erzeugten Listen.
Sollte ein Argument der Liste durch 2 ohne Rest teilbar sein, ist das Ergebnis von exists true andernfalls ist das Ergebnis
false.
object ListExists {
def main(args: Array[String]) {
val list1 = List(1,2,4,5,7)
val list2 = List(1,3,5,7)
val myFunction = (x: Int) => x % 2 == 0
println(list1.exists(myFunction))
println(list2.exists(myFunction))
}
}
timpt.de - X2H V 0.11
Die Ausführung des Programmes führt zu folgender Ausgabe auf der Systemausgabe:
true
false
filter
def filter (p: (A) => Boolean) : List[A]
Erzeugt eine Liste bestehend aus Elementen der Ausgangsliste, die eine
zu definierende Bedingung erfüllen. Die zu erfüllende Bedingung
wird der Methode filter über eine Funktion mitgeteilt.
Zur Demonstration der Methode filter definieren wir
eine List mit Elementen des Datentyps Int:
scala> val list1 = List(1,33,26,146,32,55,26,217,24,326)
list1: List[Int] = List(1, 33, 26, 146, 32, 55, 26, 217, 24, 326)
Nun erzeugen wir eine neue List über die Methode filter
mit allem Elementen aus list1 die größer 50 sind.
Um dies zu erreichen, definieren wir beim Aufruf der Methode filter
ein Funktionsliteral innerhalb der Klammern der Methode.
scala> val list2 = list1.filter((x: Int) => x > 50)
list2: List[Int] = List(146, 55, 217, 326)
Da die List nur aus Int Werten besteht, kann der Scala Compiler
den Typ der Variablen über Typableitung (type inference) bestimmen. Daher
muss der Typ der Variablen x in der Funktion nicht angegeben werden.
scala> val list3 = list1.filter(x => x < 30)
list3: List[Int] = List(1, 26, 26, 24)
Da filter immer ein Element der Filter-Funktion übergibt,
kann die Schreibweise der Funktion weiter vereinfacht werden und auf den
übergebenen Parameter mit dem Unterstrich zugegriffen werden.
scala> val list4 = list1.filter(_ > 100)
list4: List[Int] = List(146, 217, 326)
Definiert ist filter im Trait scala.collection.TraversableLike.
foreach
def foreach (f: (A) => Unit) : Unit
def foreach [B] (f: (A) => B) : Unit
Die Methode foreach iteriert über alle Elemente der Liste,
welche in einer zu übergebenen Funktion verarbeitet werden können.
Das nachfolgende Beispiel zeigt die Verwendung von foreach
mit einem Funktionsliteral, welches die enthaltenen Elemente auf der
Systemausgabe ausgibt.
object MyListTest {
def main(args: Array[String]) {
val myList = List(1,6,3,9,4)
myList.foreach(i => println(i))
}
}
timpt.de - X2H V 0.10
Die Ausführung dieses Programmes führt zu folgender Ausgabe auf der Systemausgabe:
1
6
3
9
4
Definiert ist foreach im Trait scala.collection.IterableLike,
welche im Trait scala.collection.LinearSeqOptimized implementiert wird.
head
def head : A
Die Funktion head liefert das erste Element einer Liste.
Der nachfolgende Quelltext zeigt beispielhaft die Verwendung der Funktion head.
object MyListHeadTest {
def main(args: Array[String]) {
val myList = List(4,3,2,1)
val headOfList = myList.head
println(headOfList)
}
}
timpt.de - X2H V 0.10
Als Ergebnis des Programmablaufs wird der Int-Wert 4 auf
der Systemausgabe ausgegeben. Definiert ist die Funktion head
im Trait scala.collection.TraversableLike und wird
im Train scalc.collection.IterableLike überschrieben.
map
def map [B] (f: (A) ? B): List[B]
def map [B, That] (f: (A) ? B)(implicit bf: CanBuildFrom[List[A], B, That]): That
map erzeugt eine neue Liste durch Anwendung einer Funktion auf alle Elemente der Ausgangsliste.
Im nachfolgenden Beispiel wird auf jedes Element der Ausgangsliste eine Funktion angewendet,
welche jeden Wert mit 2 multipliziert. Das jeweilige Listenelement wird in der Funktion durch den
Unterstrich repräsentiert.
object TheMapFunction {
def main(args: Array[String]) {
val list1 = List(1,2,3,4)
val list2 = list1 map (_ * 2)
println(list1)
println(list2)
}
}
timpt.de - X2H V 0.11
Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:
List(1, 2, 3, 4)
List(2, 4, 6, 8)
reduceLeft
reduceLeft [B >: A] (f: (B, A) => B) : B
reduceLeft iteriert paarweise über die Liste von der linken Seite aus
und wertet mit diesen die übergebene Funktion aus. Die Iteration beginnt mit den ersten beiden
Elementen der Liste. Das Ergebnis der Auswertung und das
nächte Element der Liste werden im Anschluss in gleicher Weise ausgewertet.
Diese Iteration wird fortgesetzt bis das Ende der Liste erreicht ist. Das Ergebnis
von reduceLeft ist das Ergebnis der letzten Auswertung.
Nachfolgend beispielhaft die Anwendung von reduceLeft
object ReduceLeft1{
def main(args: Array[String]) {
val myList = List(1,4,5,8,5,2,5)
myList.reduceLeft{(a,b) =>
if (a > b) {
println("true "+a+" "+b)
a * 2
}
else {
println("false "+a+" "+b)
b
}
}
}
}
timpt.de - X2H V 0.10
Die Ausführung des Programmes führt zu folgender Ausgabe:
false 1 4
false 4 5
false 5 8
true 8 5
true 16 2
true 32 5
object ReduceLeft2 {
def main(args: Array[String]) {
val myList = List(1,4,5,8,5,2,5)
println(myList.reduceLeft((a,b) => test(a,b)))
}
def test(v1: Int, v2: Int) = if (v2 > v1) v2 else v1
}
timpt.de - X2H V 0.10
Die Ausführung des Programmes führt zum Ergebnis 8.
Definiert wird reduceLeft im Trait scala.collection.TraversableOnce
und wird im Trait scala.collection.LinearSeqOptimized implementiert.
reverse: List:[A]
def reverse : List[A]
Die Methode reverse: List[A] liefert eine List mit allen Elementen der Ursprungsliste,
wobei die Elemente in umgekehrter Reihenfolge enthalten sind.
object ListReverse {
def main(args: Array[String]) {
val myList = List(1,2,3,4)
println(myList)
val reverseList = myList.reverse
println(reverseList)
}
}
timpt.de - X2H V 0.10
Die Ausführung des Programms führt zu folgender Ausgabe auf der Systemausgabe:
List(1, 2, 3, 4)
List(4, 3, 2, 1)
size
def size : Int
Die Funktion size der Klasse List liefert die Anzahl Elemente, die in der List enthalten sind.
Das nachfolgende Beispiel erzeugt zunächst eine Liste mit 5 Elementen. In der nachfolgenden Systemausgabe wird
die Anzahl der Elemente ausgegeben.
object ListSize extends Application{
val myList = List(1,2,3,4,5)
println(myList.size)
}
timpt.de - X2H V 0.10
tail
def tail : List[A]
tail liefert eine neue List, ohne das erste Element der List
auf dem tail aufgerufen wurde. Das nachfolgende Skript zeigt beispielhaft die Anwendung
von tail.
val list1 = List(1,2,3,4,5,6) val list2 = list1.tail println(list1) println(list2)timpt.de - X2H V 0.10
Der Ablauf des Skriptes führt zu folgender Ausgabe auf der Systemausgabe:
List(1, 2, 3, 4, 5, 6)
List(2, 3, 4, 5, 6)