Мне нужна функция карты . Есть ли что-то подобное в Java?
(Для тех, кто задается вопросом: я, конечно, знаю, как реализовать эту тривиальную функцию сам ...)
Мне нужна функция карты . Есть ли что-то подобное в Java?
(Для тех, кто задается вопросом: я, конечно, знаю, как реализовать эту тривиальную функцию сам ...)
Ответы:
В java 6 нет понятия функции в JDK.
Однако у Guava есть функциональный интерфейс, и
метод обеспечивает необходимую вам функциональность.
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);
Collections2.transform(input -> Integer.toHexString(intput.intValue())
Начиная с 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()
.
toList()
. Замена на другой тип:(List<R>)((List) list).replaceAll(o -> doMap((E) o));
e -> doMap(e)
заменить просто doMap
?
foo::doMap
или Foo::doMap
.
Существует замечательная библиотека под названием Functional Java, которая обрабатывает многие вещи, которые вы хотели бы иметь в Java, но это не так. Опять же, есть еще этот замечательный язык Scala, который делает все, что должна была делать Java, но не делает, но при этом остается совместимым с чем-либо, написанным для JVM.
a.map({int i => i + 42});
расширили ли они компилятор? или добавлен препроцессор?
Будьте очень осторожны с Collections2.transform()
гуавой. Самым большим преимуществом этого метода является его самая большая опасность: его лень.
Посмотрите документацию 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()
вот метод карты. Он использует те же "обратные вызовы" Function <>, что и Collections.transform()
. Список, который вы получите, доступен только для чтения, используйте его copyInto()
для получения списка для чтения и записи.
В противном случае, конечно, когда java8 выйдет с лямбдами, это будет устаревшим.
Это еще одна функциональная библиотека, с которой вы можете использовать карту: http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
Хотя это старый вопрос, я хотел бы показать другое решение:
Просто определите свою собственную операцию, используя java generics и 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());
}
Тогда вы можете написать такой код:
List<String> hex = map(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);