Necesito una función de mapa . ¿Hay algo como esto en Java ya?
(Para aquellos que se preguntan: por supuesto, sé cómo implementar esta función trivial yo mismo ...)
Necesito una función de mapa . ¿Hay algo como esto en Java ya?
(Para aquellos que se preguntan: por supuesto, sé cómo implementar esta función trivial yo mismo ...)
Respuestas:
No hay una noción de una función en el JDK a partir de java 6.
Sin embargo, Guava tiene una interfaz de función y el
método proporciona la funcionalidad que necesita.
Collections2.transform(Collection<E>, Function<E,E2>)
Ejemplo:
// 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);
Salida:
[a, 14, 1e, 28, 32]
En estos días, con Java 8, en realidad hay una función de mapa, por lo que probablemente escribiría el código de una manera más concisa:
Collection<String> hex = input.stream()
.map(Integer::toHexString)
.collect(Collectors::toList);
Collections2.transform(input -> Integer.toHexString(intput.intValue())
Desde Java 8, hay algunas opciones estándar para hacer esto en 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());
Ver java.util.Collection.stream()
y java.util.stream.Collectors.toList()
.
toList()
. Sustitución a otro tipo:(List<R>)((List) list).replaceAll(o -> doMap((E) o));
e -> doMap(e)
puede reemplazar por solo doMap
?
foo::doMap
o Foo::doMap
.
Hay una biblioteca maravillosa llamada Functional Java que maneja muchas de las cosas que le gustaría que Java tuviera pero no las tiene. Por otra parte, también está este maravilloso lenguaje Scala que hace todo lo que Java debería haber hecho, pero no lo hace mientras sigue siendo compatible con cualquier cosa escrita para la JVM.
a.map({int i => i + 42});
¿extendieron el compilador? o preprocesador agregado?
Ten mucho cuidado con la Collections2.transform()
guayaba. La mayor ventaja de ese método es también su mayor peligro: su pereza.
Mire la documentación de Lists.transform()
, que creo que se aplica también a Collections2.transform()
:
La función se aplica perezosamente, se invoca cuando es necesario. Esto es necesario para que la lista devuelta sea una vista, pero significa que la función se aplicará muchas veces para operaciones masivas como List.contains (java.lang.Object) y List.hashCode (). Para que esto funcione bien, la función debe ser rápida. Para evitar una evaluación diferida cuando la lista devuelta no necesita ser una vista, copie la lista devuelta en una nueva lista de su elección.
También en la documentación de Collections2.transform()
que mencionan que obtienes una vista en vivo, ese cambio en la lista fuente afecta la lista transformada. Este tipo de comportamiento puede conducir a problemas difíciles de rastrear si el desarrollador no se da cuenta de cómo funciona.
Si quieres un "mapa" más clásico, que se ejecutará una vez y solo una vez, entonces es mejor que FluentIterable
, también de Guava, que tiene una operación que es mucho más simple. Aquí está el ejemplo de Google para ello:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
Aquí está el método de mapa. Utiliza la misma función <> "devoluciones de llamada" que Collections.transform()
. Sin embargo, la lista que obtiene es de solo lectura, úsela copyInto()
para obtener una lista de lectura y escritura.
De lo contrario, por supuesto, cuando java8 salga con lambdas, esto será obsoleto.
Esta es otra biblioteca funcional con la que puede usar el mapa: http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
Aunque es una vieja pregunta, me gustaría mostrar otra solución:
Simplemente defina su propia operación utilizando java generics y java 8 streams:
public static <S, T> List<T> map(Collection<S> collection, Function<S, T> mapFunction) {
return collection.stream().map(mapFunction).collect(Collectors.toList());
}
Entonces puedes escribir código como este:
List<String> hex = map(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);