Ich brauche eine Kartenfunktion . Gibt es so etwas schon in Java?
(Für diejenigen, die sich fragen: Ich weiß natürlich, wie man diese triviale Funktion selbst implementiert ...)
Ich brauche eine Kartenfunktion . Gibt es so etwas schon in Java?
(Für diejenigen, die sich fragen: Ich weiß natürlich, wie man diese triviale Funktion selbst implementiert ...)
Antworten:
Es gibt keine Vorstellung von einer Funktion im JDK ab Java 6.
Guava verfügt jedoch über eine Funktionsschnittstelle und die
Methode bietet die von Ihnen benötigte Funktionalität.
Collections2.transform(Collection<E>, Function<E,E2>)
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);
Ausgabe:
[a, 14, 1e, 28, 32]
Heutzutage gibt es mit Java 8 tatsächlich eine Kartenfunktion, daher würde ich den Code wahrscheinlich präziser schreiben:
Collection<String> hex = input.stream()
.map(Integer::toHexString)
.collect(Collectors::toList);
Collections2.transform(input -> Integer.toHexString(intput.intValue())
Seit Java 8 gibt es einige Standardoptionen, um 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()
.
toList()
. Ersetzen auf einen anderen Typ:(List<R>)((List) list).replaceAll(o -> doMap((E) o));
e -> doMap(e)
durch nur ersetzt werden doMap
?
foo::doMap
oder Foo::doMap
.
Es gibt eine wunderbare Bibliothek namens Functional Java, die viele der Dinge behandelt, die Java haben soll, aber nicht. Andererseits gibt es auch diese wunderbare Sprache Scala, die alles tut, was Java hätte tun sollen, aber nicht mit allem kompatibel ist, was für die JVM geschrieben wurde.
a.map({int i => i + 42});
Haben sie den Compiler erweitert? oder Präprozessor hinzugefügt?
Seien Sie sehr vorsichtig mit Collections2.transform()
Guaven. Der größte Vorteil dieser Methode ist auch ihre größte Gefahr: ihre Faulheit.
Schauen Sie sich die Dokumentation an Lists.transform()
, von der ich glaube, dass sie auch gilt für Collections2.transform()
:
Die Funktion wird träge angewendet und bei Bedarf aufgerufen. Dies ist erforderlich, damit die zurückgegebene Liste eine Ansicht ist. Dies bedeutet jedoch, dass die Funktion für Massenoperationen wie List.contains (java.lang.Object) und List.hashCode () mehrmals angewendet wird. Damit dies gut funktioniert, sollte die Funktion schnell sein. Kopieren Sie die zurückgegebene Liste in eine neue Liste Ihrer Wahl, um eine verzögerte Auswertung zu vermeiden, wenn die zurückgegebene Liste keine Ansicht sein muss.
Auch in der Dokumentation wird Collections2.transform()
erwähnt, dass Sie eine Live-Ansicht erhalten, die sich in der Quellliste auf die transformierte Liste auswirkt. Diese Art von Verhalten kann zu schwer zu verfolgenden Problemen führen, wenn der Entwickler nicht erkennt, wie es funktioniert.
Wenn Sie eine klassischere "Karte" möchten, die nur einmal ausgeführt wird, sind Sie besser dran FluentIterable
, auch von Guava aus, die eine viel einfachere Operation hat. Hier ist das Google-Beispiel dafür:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
Hier ist die Kartenmethode. Es verwendet die gleiche Funktion <> "Rückrufe" wie Collections.transform()
. Die Liste, die Sie zurückerhalten, ist schreibgeschützt. Verwenden Sie diese Option, copyInto()
um eine Lese- / Schreibliste abzurufen.
Andernfalls ist dies natürlich veraltet, wenn Java8 mit Lambdas herauskommt.
Dies ist eine weitere funktionale Bibliothek, mit der Sie map verwenden können: http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
Obwohl es eine alte Frage ist, möchte ich eine andere Lösung zeigen:
Definieren Sie einfach Ihre eigene Operation mit Java Generics und Java 8 Streams:
public static <S, T> List<T> map(Collection<S> collection, Function<S, T> mapFunction) {
return collection.stream().map(mapFunction).collect(Collectors.toList());
}
Dann können Sie Code wie folgt schreiben:
List<String> hex = map(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);