J'ai besoin d'une fonction de carte . Existe-t-il déjà quelque chose comme ça en Java?
(Pour ceux qui se demandent: je sais bien sûr implémenter moi-même cette fonction triviale ...)
J'ai besoin d'une fonction de carte . Existe-t-il déjà quelque chose comme ça en Java?
(Pour ceux qui se demandent: je sais bien sûr implémenter moi-même cette fonction triviale ...)
Réponses:
Il n'y a pas de notion de fonction dans le JDK à partir de java 6.
Guava a une interface Function et la
méthode fournit les fonctionnalités dont vous avez besoin.
Collections2.transform(Collection<E>, Function<E,E2>)
Exemple:
// 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);
Production:
[a, 14, 1e, 28, 32]
De nos jours, avec Java 8, il existe en fait une fonction de carte, donc j'écrirais probablement le code de manière plus concise:
Collection<String> hex = input.stream()
.map(Integer::toHexString)
.collect(Collectors::toList);
Collections2.transform(input -> Integer.toHexString(intput.intValue())
Depuis Java 8, il existe des options standard pour faire cela dans 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());
Voir java.util.Collection.stream()
et java.util.stream.Collectors.toList()
.
toList()
. Remplacement par un type différent:(List<R>)((List) list).replaceAll(o -> doMap((E) o));
e -> doMap(e)
être remplacé par juste doMap
?
foo::doMap
ou Foo::doMap
.
Il existe une merveilleuse bibliothèque appelée Functional Java qui gère beaucoup de choses que vous voudriez que Java ait, mais ce n'est pas le cas. Là encore, il y a aussi ce merveilleux langage Scala qui fait tout ce que Java aurait dû faire mais ne le fait pas tout en étant compatible avec tout ce qui est écrit pour la JVM.
a.map({int i => i + 42});
ont-ils étendu le compilateur? ou préprocesseur ajouté?
Soyez très prudent avec Collections2.transform()
de la goyave. Le plus grand avantage de cette méthode est aussi son plus grand danger: sa paresse.
Regardez la documentation de Lists.transform()
, qui, je crois, s'applique également à Collections2.transform()
:
La fonction est appliquée paresseusement, appelée en cas de besoin. Cela est nécessaire pour que la liste retournée soit une vue, mais cela signifie que la fonction sera appliquée plusieurs fois pour des opérations en bloc comme List.contains (java.lang.Object) et List.hashCode (). Pour que cela fonctionne bien, la fonction doit être rapide. Pour éviter une évaluation paresseuse lorsque la liste renvoyée n'a pas besoin d'être une vue, copiez la liste renvoyée dans une nouvelle liste de votre choix.
Dans la documentation, Collections2.transform()
ils mentionnent également que vous obtenez une vue en direct, ce changement dans la liste source affecte la liste transformée. Ce type de comportement peut entraîner des problèmes difficiles à suivre si le développeur ne réalise pas comment cela fonctionne.
Si vous voulez une "carte" plus classique, qui ne fonctionnera qu'une seule fois, alors vous feriez mieux d'utiliser FluentIterable
, également depuis Guava, qui a une opération beaucoup plus simple. Voici l'exemple google pour cela:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
voici la méthode de la carte. Il utilise les mêmes fonctions <> "callbacks" que Collections.transform()
. La liste que vous récupérez est en lecture seule, utilisez copyInto()
pour obtenir une liste en lecture-écriture.
Sinon, bien sûr, lorsque java8 sortira avec des lambdas, ce sera obsolète.
Voici une autre bibliothèque fonctionnelle avec laquelle vous pouvez utiliser map: http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
Même si c'est une vieille question, j'aimerais montrer une autre solution:
Définissez simplement votre propre opération à l'aide des génériques java et des flux java 8:
public static <S, T> List<T> map(Collection<S> collection, Function<S, T> mapFunction) {
return collection.stream().map(mapFunction).collect(Collectors.toList());
}
Ensuite, vous pouvez écrire du code comme celui-ci:
List<String> hex = map(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);