web-dev-qa-db-fra.com

Java: existe-t-il une fonction map?

J'ai besoin d'une fonction map . Existe-t-il déjà quelque chose comme ceci dans Java?

(Pour ceux qui se demandent: je sais bien sûr comment mettre en œuvre cette fonction triviale moi-même ...)

133
Albert

Il n’existe pas de notion de fonction dans le JDK à partir de Java 6.

Guava possède une interface Fonction et le
Collections2.transform(Collection<E>, Function<E,E2>)
La méthode fournit les fonctionnalités dont vous avez besoin.

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);

Sortie:

[a, 14, 1e, 28, 32]

Ces jours-ci, avec Java 8, il y a 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);
85
Sean Patrick Floyd

Depuis Java 8, certaines options standard permettent de le faire 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() .

89
leventov

Il existe une merveilleuse bibliothèque appelée Java fonctionnel , qui gère la plupart des choses que vous voudriez Java, mais ce n'est pas le cas. Encore une fois, il y a aussi ce merveilleux language Scala qui fait tout Java aurait dû le faire mais ne le fait pas tout en restant compatible avec tout ce qui est écrit pour la JVM.

26
wheaties

Soyez très prudent avec Collections2.transform() de goyave. Le plus grand avantage de cette méthode est également 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, invoquée si nécessaire. Cela est nécessaire pour que la liste renvoyée soit une vue, mais cela signifie que la fonction sera appliquée plusieurs fois pour des opérations en bloc telles que 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 dans une nouvelle liste de votre choix.

De plus, dans la documentation de Collections2.transform(), ils mentionnent que vous obtenez une vue en direct, que les modifications apportées à la liste source affectent 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 il fonctionne.

Si vous voulez une "carte" plus classique, qui ne sera exécutée qu'une fois, alors il vaut mieux utiliser FluentIterable , également de Guava, qui a une opération beaucoup plus simple. Voici l'exemple de 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 la même fonction <> "callbacks" que Collections.transform(). La liste que vous récupérez est en lecture seule, utilisez cependant copyInto() pour obtenir une liste en lecture-écriture.

Sinon, bien sûr, lorsque Java8 sortira avec lambdas, ce sera obsolète.

9
Emmanuel Touzery

C’est 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"
2
Pedro Morte Rolo

Même si c'est une vieille question, je voudrais montrer une autre solution:

Définissez simplement votre propre opération en utilisant Java génériques et Java 8 flux:

public static <S, T> List<T> mapAll(Collection<S> collection, Function<S, T> mapper) {
   return collection.stream().map(mapper).collect(Collectors.toList());
}

Alors vous pouvez écrire du code comme ceci:

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