webentwicklung-frage-antwort-db.com.de

Java: Gibt es eine Kartenfunktion?

Ich brauche eine map Funktion. Gibt es so etwas schon in Java?

(Für diejenigen, die sich fragen: Ich weiß natürlich, wie ich diese triviale Funktion selbst implementieren kann ...)

133
Albert

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

Guave hat eine Funktion Schnittstelle und die
Collections2.transform(Collection<E>, Function<E,E2>)
Die Methode bietet die von Ihnen benötigte Funktionalität.

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]

In diesen Tagen gibt es mit Java 8 tatsächlich eine Kartenfunktion, daher würde ich den Code wahrscheinlich prägnanter schreiben:

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

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() .

89
leventov

Es gibt eine wunderbare Bibliothek mit dem Namen Functional Java , die viele der Dinge erledigt, die Sie gerne hätten Java), aber nicht. Andererseits gibt es auch diese wunderbare Bibliothek language Scala das alles macht Java) hätte tun sollen, aber es ist noch nicht kompatibel mit irgendetwas, das für die JVM geschrieben wurde.

26
wheaties

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

Schauen Sie sich die Dokumentation von Lists.transform() an, die meines Erachtens auch für Collections2.transform() gilt:

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 () häufig angewendet wird. Damit dies gut funktioniert, sollte die Funktion schnell sein. Um eine verzögerte 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() wird erwähnt, dass Sie eine Live-Ansicht erhalten, die Änderungen in der Quellliste sich auf die transformierte Liste auswirken. Diese Art von Verhalten kann zu schwer nachvollziehbaren Problemen führen, wenn der Entwickler nicht weiß, wie es funktioniert.

Wenn Sie eine klassischere "Karte" wollen, die nur ein einziges Mal ausgeführt wird, dann sind Sie mit FluentIterable , ebenfalls aus Guava, besser dran einfacher. 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 jedoch schreibgeschützt. Verwenden Sie copyInto(), um eine Lese-/Schreibliste abzurufen.

Andernfalls ist dies natürlich veraltet, wenn Java8 mit Lambdas herauskommt.

9

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"
2

Auch wenn 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> mapAll(Collection<S> collection, Function<S, T> mapper) {
   return collection.stream().map(mapper).collect(Collectors.toList());
}

Dann können Sie Code wie folgt schreiben:

List<String> hex = mapAll(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);
1
IPP Geek