Ich habe eine Situation, in der ich eine einzelne Elementliste an eine Methode übergebe. Innerhalb dieser Methode wird das einzelne Element in der Liste um eins erhöht. Nach dem Methodenaufruf wird also das erste Element der Liste geändert (um eins erhöht).
Code ist wie folgt:
%Vor%......
%Vor%Natürlich funktioniert der obige Code in Scala nicht. Ich schaute auf ListBuffer , aber ich finde das scala doc schwer zu finden Folgen. Scala doc ist in zwei Gruppen unterteilt: Typ Mitglieder und Wert Mitglieder. In type member gibt es die Klasse WithFiler und value members hat viele Methoden. Wie kann ich WithFiler verwenden (wahrscheinlich nicht direkt mit dieser Frage verbunden, aber ich möchte verstehen, wie man scala doc benutzt).
ListBuffer scheint die richtige Lösung für dieses Problem zu sein, wenn ich eine sehr hohe Leistung haben will (die someMethod wird Millionen Mal aufgerufen) (korrigieren Sie mich, wenn ich falsch liege).
Wie löst man das obige Problem, wenn ListBuffer der richtige Listentyp ist und wenn nicht, was ist die Lösung?
In scala, der Ausdruck:
%Vor%wird wie folgt umgeschrieben:
%Vor% Die Methode update
ist nicht für den Obertyp List
definiert, da Listen unveränderlich sein können. Dies ist jedoch der Typ des Funktionsarguments.
Sie müssen also nur ListBuffers (oder einen veränderlichen Supertyp) verwenden:
%Vor% Wenn Sie auf Elemente nach Indizes zugreifen müssen, verwenden Sie stattdessen stattdessen ArrayBuffer
. Es sollte als Java ArrayList
funktionieren.
Schließlich, wenn Sie nicht über WithFilter
sachen nachdenken müssen. Verwenden Sie einfach die Methode filter
.
Das hat den Geruch einer vorzeitigen Mikrooptimierung darüber.
Es gibt zwar berechtigte Gründe für die Verwendung von Änderbarkeit (einschließlich Optimierung), aber Sie haben nicht angegeben, warum Sie glauben, dass Ihre Verwendung gültig ist, oder das größere Problem, das Sie lösen möchten. Insbesondere sind unveränderliche Listen sehr effizient, wenn sie das Ende nehmen und einen neuen Kopf voranstellen - 100% der Nicht-Kopf-Elemente werden zwischen der ursprünglichen und der neuen Liste geteilt.
Wie Sie sehen, ist die sauberste Lösung für Ihre Anforderungen,% ce_de% zu vergessen, bei einer unveränderlichen ListBuffer
zu bleiben und List
zu implementieren, ohne auf Nebenwirkungen zurückzugreifen.
Wenn andererseits ein Performance-Hotspot ist und Sie keine Möglichkeit finden, die Leistung zu verbessern, indem Sie den Algorithmus ändern, sollten Sie ein Array ist der einzige vereinheitlichte Sammlungstyp auf der JVM. Daher können Sie direkt mit Grundelementen in einem Array arbeiten und das Boxing / Unboxing vermeiden, mit dem andere Auflistungstypen zu kämpfen haben. Der Vorteil hier hat nichts mit Veränderbarkeit vs. Unveränderlichkeit zu tun; Die Leistungskosten des Unboxing / Boxens sind weit höher als die Leistungskosten (falls vorhanden) der Verwendung einer unveränderlichen Liste. someMethod
Sie können das obige natürlich umschreiben, um ListBuffer
zu verwenden, aber wenn Sie nur eine semantische Call-by-Reference Semantik für ein einzelnes Int
wollen, ist das nicht unbedingt die effizienteste Lösung. ArrayBuffer
sollte ein bisschen besser sein. Sie könnten auch so etwas tun:
Ich versuche normalerweise, meinen Code neu zu schreiben, um zu vermeiden, veränderbare Sammlungen für diese Art von Dingen zu verwenden. Zum Beispiel könnten Sie einfach den neuen Wert zurückgeben:
%Vor%Wenn Sie ListBuffer verwenden möchten, müssen Sie nur das Wort "List" in Ihrem Code für "ListBuffer" ersetzen. Allerdings würde ich die Nebeneffekt-Funktion (Ihr someMethod: Unit) komplett vermeiden, wie es naten nahe legt.
ListBuffer hat "hohe Leistung" - der Hauptzweck ist jedoch das Hinzufügen von Elementen / Ändern der Sammlung. Wenn ich es richtig verstanden habe, aktualisieren Sie das Objekt in einer Objektkollektion millionenfach - Array ist dafür ausreichend.
Tags und Links scala