Eu preciso de uma função de mapa . Já existe algo assim em Java?
(Para aqueles que se perguntam: é claro que sei como implementar essa função trivial ...)
Eu preciso de uma função de mapa . Já existe algo assim em Java?
(Para aqueles que se perguntam: é claro que sei como implementar essa função trivial ...)
Respostas:
Não há noção de uma função no JDK a partir do java 6.
A goiaba possui uma interface Function e o
método fornece a funcionalidade que você precisa.
Collections2.transform(Collection<E>, Function<E,E2>)
Exemplo:
// 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);
Resultado:
[a, 14, 1e, 28, 32]
Hoje em dia, com o Java 8, existe na verdade uma função de mapa, então eu provavelmente escreveria o código de uma maneira mais concisa:
Collection<String> hex = input.stream()
.map(Integer::toHexString)
.collect(Collectors::toList);
Collections2.transform(input -> Integer.toHexString(intput.intValue())
Desde o Java 8, existem algumas opções padrão para fazer isso no 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());
Veja java.util.Collection.stream()
e java.util.stream.Collectors.toList()
.
toList()
. Substituindo para outro tipo:(List<R>)((List) list).replaceAll(o -> doMap((E) o));
e -> doMap(e)
ser substituído por apenas doMap
?
foo::doMap
ou Foo::doMap
.
Existe uma biblioteca maravilhosa chamada Java funcional que lida com muitas das coisas que você gostaria que o Java tivesse, mas não. Por outro lado, também há esta maravilhosa linguagem Scala, que faz tudo o que Java deveria ter feito, mas ainda não é compatível com qualquer coisa escrita para a JVM.
a.map({int i => i + 42});
eles estenderam o compilador? ou pré-processador adicionado?
Tenha muito cuidado com a Collections2.transform()
goiaba. A maior vantagem desse método também é seu maior perigo: sua preguiça.
Veja a documentação da Lists.transform()
qual acredito que também se aplica a Collections2.transform()
:
A função é aplicada preguiçosamente, invocada quando necessário. Isso é necessário para que a lista retornada seja uma visualização, mas significa que a função será aplicada várias vezes para operações em massa como List.contains (java.lang.Object) e List.hashCode (). Para que isso funcione bem, a função deve ser rápida. Para evitar uma avaliação lenta quando a lista retornada não precisar ser uma visualização, copie a lista retornada para uma nova lista de sua escolha.
Também na documentação Collections2.transform()
mencionada, você obtém uma visualização ao vivo, que a mudança na lista de fontes afeta a lista transformada. Esse tipo de comportamento pode levar a problemas difíceis de rastrear se o desenvolvedor não perceber o modo como funciona.
Se você deseja um "mapa" mais clássico, que será executado uma vez e apenas uma vez, é melhor usar FluentIterable
também o Guava, que possui uma operação muito mais simples. Aqui está o exemplo do google para isso:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
aqui está o método do mapa. Ele usa a mesma função <> "retornos de chamada" que Collections.transform()
. A lista que você voltar é somente leitura, use copyInto()
para obter uma lista de leitura e gravação.
Caso contrário, é claro que quando o java8 sair com lambdas, isso será obsoleto.
Esta é outra biblioteca funcional com a qual você pode usar o mapa: http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
Mesmo que seja uma pergunta antiga, gostaria de mostrar outra solução:
Basta definir sua própria operação usando java generics e 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());
}
Então você pode escrever um código como este:
List<String> hex = map(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);