Ho bisogno di una funzione mappa . C'è già qualcosa del genere in Java?
(Per coloro che si chiedono: ovviamente so come implementare questa banale funzione da solo ...)
Ho bisogno di una funzione mappa . C'è già qualcosa del genere in Java?
(Per coloro che si chiedono: ovviamente so come implementare questa banale funzione da solo ...)
Risposte:
Non esiste alcuna idea di una funzione nel JDK come di Java 6.
Guava ha comunque un'interfaccia Function e il
metodo fornisce le funzionalità richieste.
Collections2.transform(Collection<E>, Function<E,E2>)
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);
Produzione:
[a, 14, 1e, 28, 32]
In questi giorni, con Java 8, esiste in realtà una funzione di mappa, quindi probabilmente scriverei il codice in un modo più conciso:
Collection<String> hex = input.stream()
.map(Integer::toHexString)
.collect(Collectors::toList);
Collections2.transform(input -> Integer.toHexString(intput.intValue())
Da Java 8, ci sono alcune opzioni standard per farlo 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());
Vedi java.util.Collection.stream()
e java.util.stream.Collectors.toList()
.
toList()
. Sostituzione di diverso tipo:(List<R>)((List) list).replaceAll(o -> doMap((E) o));
e -> doMap(e)
essere sostituito con solo doMap
?
foo::doMap
o Foo::doMap
.
C'è una meravigliosa libreria chiamata Functional Java che gestisce molte delle cose che vorresti avere Java ma non lo fa. Poi di nuovo, c'è anche questo meraviglioso linguaggio Scala che fa tutto ciò che Java avrebbe dovuto fare ma non lo fa pur essendo compatibile con qualsiasi cosa scritta per JVM.
a.map({int i => i + 42});
hanno esteso il compilatore? o aggiunto preprocessore?
Stai molto attento con Collections2.transform()
dalla guava. Il più grande vantaggio di quel metodo è anche il suo più grande pericolo: la sua pigrizia.
Guarda la documentazione di Lists.transform()
, che credo valga anche per Collections2.transform()
:
La funzione viene applicata pigramente, invocata quando necessario. Ciò è necessario affinché l'elenco restituito sia una vista, ma significa che la funzione verrà applicata molte volte per operazioni in blocco come List.contains (java.lang.Object) e List.hashCode (). Perché ciò funzioni bene, la funzione dovrebbe essere veloce. Per evitare una valutazione pigra quando l'elenco restituito non deve essere una vista, copiare l'elenco restituito in un nuovo elenco di propria scelta.
Anche nella documentazione di Collections2.transform()
cui parlano si ottiene una vista dal vivo, che le modifiche all'elenco delle fonti influiscono sull'elenco trasformato. Questo tipo di comportamento può portare a problemi difficili da rintracciare se lo sviluppatore non si rende conto del modo in cui funziona.
Se vuoi una "mappa" più classica, che verrà eseguita una volta e una volta sola, allora stai meglio FluentIterable
, anche da Guava, che ha un'operazione che è molto più semplice. Ecco l'esempio di Google per questo:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
ecco il metodo della mappa. Utilizza la stessa funzione <> "callbacks" di Collections.transform()
. L'elenco che ricevi è di sola lettura, usa copyInto()
per ottenere un elenco di lettura-scrittura.
Altrimenti ovviamente quando java8 esce con lambda, questo sarà obsoleto.
Questa è un'altra libreria funzionale con cui puoi usare map: http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
Anche se è una vecchia domanda, vorrei mostrare un'altra soluzione:
Basta definire la propria operazione usando java generics e java 8 stream:
public static <S, T> List<T> map(Collection<S> collection, Function<S, T> mapFunction) {
return collection.stream().map(mapFunction).collect(Collectors.toList());
}
Quindi puoi scrivere codice in questo modo:
List<String> hex = map(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);