Java: c'è una funzione di mappa?
-
29-09-2019 - |
Domanda
Ho bisogno di un mappa funzione. C'è qualcosa di simile in Java già?
(Per coloro che si chiedono: Io naturalmente sapere come implementare questa funzione banale me stesso ...)
Soluzione
Non v'è alcuna nozione di una funzione nel JDK come di Java 6.
Guava ha un interfaccia Funzione e anche se il
Collections2.transform(Collection<E>, Function<E,E2>)
metodo fornisce le funzionalità desiderate.
Esempio:
// 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);
Output:
[a, 14, 1e, 28, 32]
In questi giorni, con Java 8, v'è in realtà una funzione di mappa, così probabilmente sarei scrivere il codice in modo più conciso:
Collection<String> hex = input.stream()
.map(Integer::toHexString)
.collect(Collectors::toList);
Altri suggerimenti
Dato che Java 8, ci sono alcune opzioni standard per fare questo in JDK:
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());
java.util.Collection.stream()
e java.util.stream.Collectors.toList()
.
C'è una meravigliosa libreria chiamata Funzionale Java che gestisce molte delle cose che ci si vuole Java per avere, ma non lo fa. Poi di nuovo, c'è anche questa lingua meravigliosa Scala che fa tutto Java avrebbe dovuto fare, ma non si pur essendo compatibile con qualsiasi cosa scritta per la JVM.
essere molto attenti con Collections2.transform()
da guava.
più grande vantaggio di questo metodo è anche il suo più grande pericolo:. la sua pigrizia
Guardate la documentazione di Lists.transform()
, che a mio avviso vale anche per Collections2.transform()
:
La funzione viene applicata pigramente, invocato quando necessario. Ciò è necessario per la lista restituita essere una visione, ma significa che la funzione sarà applicata molte volte per operazioni di massa come List.contains (java.lang.Object) e List.hashCode (). Per questo a buone prestazioni, funzione dovrebbe essere veloce. Per evitare di valutazione pigra quando l'elenco restituito non ha bisogno di essere una visione, copiare l'elenco restituito in un nuovo elenco di tua scelta.
Anche nella documentazione di Collections2.transform()
accennano si ottiene una visione dal vivo, che il cambiamento nella lista di origine influisce sulla lista trasformato. Questo tipo di comportamento può portare a problemi difficili da pista se lo sviluppatore non si rende conto del modo in cui funziona.
Se si vuole una "mappa" più classico, che verrà eseguito una sola volta e una sola volta, allora si sta meglio con FluentIterable
, anche da Guava, che ha un funzionamento che è molto più semplice. Ecco l'esempio di Google per esso:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
qui è il metodo mappa. Esso utilizza la stessa funzione di <> "callback" come Collections.transform()
. La lista che si ottiene indietro è di sola lettura, però, l'uso copyInto()
per ottenere una lista di lettura-scrittura.
In caso contrario, naturalmente, quando java8 esce con lambda, questo sarà obsoleto.
Questo è un altro lib funzionale, con il quale è possibile utilizzare la mappa: http://code.google.com / p / totallylazy /
sequence(1, 2).map(toString); // lazily returns "1", "2"
Anche se è una vecchia questione vorrei mostrare un'altra soluzione:
Basta definire il proprio funzionamento con generici Java e Java 8 flussi:
public static <S, T> List<T> mapAll(Collection<S> collection, Function<S, T> mapper) {
return collection.stream().map(mapper).collect(Collectors.toList());
}
Che è possibile scrivere codice in questo modo:
List<String> hex = mapAll(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);