2010-10-11 20 views
111

Ich brauche eine map Funktion. Gibt es sowas schon in Java?Java: Gibt es eine Kartenfunktion?

(Für diejenigen, die sich fragen: ich natürlich wissen, wie diese triviale Funktion implementieren mich ...)

+0

Wenn nicht, ist es trivial, sich selbst zu definieren. Aber ich denke, Google kennt ein Dutzend Implementierungen? – delnan

+2

Dupliziert (eher besser) bei http://stackoverflow.com/questions/3907412/java-general-function-x-y-interface – Chowlett

+5

@Chris: Wie ist es die gleiche Frage? – Albert

Antwort

73

Es gibt keine Vorstellung von einer Funktion im JDK als Java 6.

Guava hat eine Function Schnittstelle obwohl und die
Collections2.transform(Collection<E>, Function<E,E2>)
Methode bietet die Funktionalität, die Sie benötigen.

Beispiel:

// example, converts a collection of integers to their 
// hexadecimal string representations 
final Collection<Integer> input = Arrays.asList(10, 20, 30, 40, 50); 
final Collection<String> output = 
    Collections2.transform(input, new Function<Integer, String>(){ 

     @Override 
     public String apply(final Integer input){ 
      return Integer.toHexString(input.intValue()); 
     } 
    }); 
System.out.println(output); 

Ausgang:

[a, 14, 1e, 28, 32] 

diesen Tagen, mit Java 8, gibt es tatsächlich eine Map-Funktion, also würde ich wahrscheinlich das schreiben Code in einer prägnanteren Art und Weise:

Collection<String> hex = input.stream() 
           .map(Integer::toHexString) 
           .collect(Collectors::toList); 
+8

Es ist erwähnenswert, dass während du mit Guava das * kannst * vielleicht nicht willst: http: //code.google.com/p/guava-libraries/wiki/FunctionalExplained (lesen Sie den Abschnitt "Vorbehalte"). –

+2

@AdamParkin wahr, aber ich bin mir ziemlich sicher, dass bezieht sich auf fortgeschrittenere funktionale Konzepte als diese, sonst hätten sie nicht die * transform (*) Methoden in erster Linie entwickelt –

+2

Eigentlich nein, es gibt oft eine bestimmte Leistung mit funktionalen Idiomen, weshalb sie betonen, Sie sollten nur die Einrichtungen verwenden, wenn Sie sicher sind, dass es die beiden Kriterien erfüllt: Nettoeinsparungen von LOC für die Codebasis als Ganzes, und * nachgewiesene * Leistungszuwächse aufgrund von Lazy Evaluation (oder zumindest keine Performance-Hits).Sie argumentieren nicht gegen die Verwendung von ihnen, nur darauf hinweisend, dass, wenn Sie dazu kommen, Sie die Warnungen der Implementierer beachten sollten. –

21

Es gibt eine wunderbare Bibliothek mit dem Namen Functional Java, die viele der Dinge behandelt würden Sie wollen Java haben, aber es tut es nicht. Andererseits gibt es auch diese wundervolle Sprache Scala, die alles tut, was Java hätte tun sollen, aber nicht kompatibel mit allem, was für die JVM geschrieben wurde.

+0

haben könnte Ich bin interessiert, wie sie aktiviert haben folgende Syntax: 'a.map ({int i => i + 42});' haben sie den Compiler erweitert? oder hinzugefügt Präprozessor? – Andrey

+0

@Andrey - Sie können sie entweder selbst fragen oder den Quellcode überprüfen, um zu sehen, wie es gemacht wird. Hier ist ein Link zur Quelle: http://functionaljava.org/source/ – wheaties

+1

@Andrey: Beispiele verwenden Syntax von BGGA Schließungen Vorschlag. Während es einen laufenden Prototyp gibt, ist es noch nicht in 'offiziellem' Java. –

2

Dies ist eine weitere funktionelle lib mit dem Sie Karte verwenden: http://code.google.com/p/totallylazy/

sequence(1, 2).map(toString); // lazily returns "1", "2" 
+0

Hier ist ein Leitfaden zur Verwendung von TotallyLazy: http://intrepidis.blogspot.com/2013/07/using-totallylazy-functional-library.html –

9

Seien Sie sehr vorsichtig mit Collections2.transform() von Guave. Der größte Vorteil dieser Methode ist auch ihre größte Gefahr: ihre Faulheit.

Blick in die Dokumentation von Lists.transform(), die ich glaube, gilt auch für Collections2.transform():

Die Funktion träge angewendet wird, aufgerufen, wenn nötig. Dies ist notwendig für die zurückgegebene Liste, um eine Ansicht zu sein, aber es bedeutet, dass die Funktion viele Male für Massenvorgänge wie List.contains (java.lang.Object) und List.hashCode() angewendet wird. Damit dies gut funktioniert, sollte die Funktion schnell sein. Um eine faule Auswertung zu vermeiden, wenn die zurückgegebene Liste keine Ansicht sein muss, kopieren Sie die zurückgegebene Liste in eine neue Liste Ihrer Wahl.

Auch in der Dokumentation von Collections2.transform() sie erwähnen Sie eine Live-Ansicht erhalten, dass der Wandel in der Quellenliste die transformierten Liste beeinflussen. Diese Art von Verhalten kann zu schwer zu verfolgenden Problemen führen, wenn der Entwickler die Funktionsweise nicht erkennt.

Wenn Sie eine klassischere "Karte" möchten, die nur einmal ausgeführt wird, dann ist es besser, wenn Sie FluentIterable, auch aus Guava, verwenden, was eine viel einfachere Operation ist.Hier ist das Google-Beispiel dafür:

FluentIterable 
     .from(database.getClientList()) 
     .filter(activeInLastMonth()) 
     .transform(Functions.toStringFunction()) 
     .limit(10) 
     .toList(); 

transform() hier ist die Karte Methode. Es verwendet die gleiche Funktion <> "Rückrufe" wie Collections.transform(). Die Liste, die Sie erhalten, ist schreibgeschützt. Verwenden Sie copyInto(), um eine Lese-/Schreibliste zu erhalten.

Sonst natürlich, wenn java8 mit Lambdas kommt, wird dies veraltet sein.

76

Da Java 8, gibt es einige Standardoptionen dies in JDK zu tun:

Collection<E> in = ... 
Object[] mapped = in.stream().map(e -> doMap(e)).toArray(); 
// or 
List<E> mapped = in.stream().map(e -> doMap(e)).collect(Collectors.toList()); 

Siehe java.util.Collection.stream() und java.util.stream.Collectors.toList().

+97

Dies ist so viel wortreich, dass mich innerlich schmerzt. – Natix

+0

@Natix Wenn die Sammlung ArrayList ist und Sie es nach dem Mappen nicht benötigen, ist es einfacher und effizienter ['ArrayList.replaceAll'] (http://download.java.net/jdk8/docs/api/java/ util/ArrayList.html # replaceAll-java.util.function.UnaryOperator-). – leventov

+0

@Natix ausführlich, aber agil. 'stream()' oder 'parallelStream()', Sammeln zu Liste oder Set usw. Aber ich stimme zu, es sollte Abkürzungen für die häufigsten Anwendungsfälle geben. – leventov

Verwandte Themen