Мне нужна функция map. Уже есть что-то подобное в Java?
(Для тех, кто задается вопросом: я, конечно, знаю, как реализовать эту тривиальную функцию самостоятельно...)
Мне нужна функция map. Уже есть что-то подобное в Java?
(Для тех, кто задается вопросом: я, конечно, знаю, как реализовать эту тривиальную функцию самостоятельно...)
В JDK нет понятия функции java 6.
Guava имеет Function интерфейс хотя и
Collections2.transform(Collection<E>, Function<E,E2>)
метод предоставляет требуемые функции.
Пример:
// 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);
Вывод:
[a, 14, 1e, 28, 32]
В наши дни, с Java 8, на самом деле есть функция отображения, поэтому я бы скорее написал код более кратким образом:
Collection<String> hex = input.stream()
.map(Integer::toHexString)
.collect(Collectors::toList);
Начиная с Java 8, в 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());
Смотрите java.util.Collection.stream()
и java.util.stream.Collectors.toList()
.
Существует замечательная библиотека под названием Functional Java, которая обрабатывает многие вещи, которые вы хотите использовать Java, но это не так. Опять же, этот замечательный язык Scala, который делает все, что должен был сделать Java, но не все еще совместим с чем-либо написанным для JVM.
Будьте осторожны с Collections2.transform()
от guava.
Наибольшим преимуществом этого метода является его самая большая опасность: его лень.
Посмотрите документацию Lists.transform()
, которая, как я считаю, также относится к Collections2.transform()
:
Функция применяется лениво, вызывается, когда это необходимо. Это необходимо для возвращаемого списка - представление, но это означает, что функция будет применяться много раз для массовых операций, таких как List.contains(java.lang.Object) и List.hashCode(). Для этого работать хорошо, функция должна быть быстрой. Во избежание ленивой оценки, когда возвращенный список не обязательно должен быть просмотром, скопировать возвращенный список в новый список по вашему выбору.
Также в документации Collections2.transform()
упоминается, что вы получаете живое представление, что изменение в исходном списке влияет на преобразованный список. Такое поведение может привести к сложным задачам, если разработчик не понимает, как это работает.
Если вам нужна более классическая "карта", которая будет выполняться только один раз, тогда вам будет лучше FluentIterable
, также из Guava, у которого есть операция, которая намного проще. Вот пример Google для него:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
здесь - метод карты. Он использует те же функции < > "callbacks" как Collections.transform()
. Список, который вы вернете, доступен только для чтения, но используйте copyInto()
для получения списка чтения-записи.
В противном случае, конечно, когда java8 выходит с лямбдами, это будет устаревшим.
Это еще одна функциональная библиотека, с помощью которой вы можете использовать карту: http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"