Мені потрібна функція карти . Чи є щось подібне в Java вже?
(Для тих, хто цікавиться: я, звичайно, знаю, як реалізувати цю тривіальну функцію самостійно ...)
Мені потрібна функція карти . Чи є щось подібне в Java вже?
(Для тих, хто цікавиться: я, звичайно, знаю, як реалізувати цю тривіальну функцію самостійно ...)
Відповіді:
Поняття функції в JDK не існує як java 6.
У 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
.
Є чудова бібліотека під назвою Функціональна 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()
ось метод карти. Він використовує ту ж функцію <> "зворотні дзвінки", що і Collections.transform()
. Список, який ви отримуєте назад, доступний лише для читання, використовуйте copyInto()
для отримання списку читання-запису.
Інакше, звичайно, коли java8 вийде з лямбдами, це буде застарілим.
Це ще одна функціональна вкладка, з якою ви можете використовувати карту: http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
Хоча це старе питання, я хотів би показати інше рішення:
Просто визначте власну операцію за допомогою Java generics та потоків java 8:
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);