Понимание Python-списка в Java
Так как Java не позволяет передавать методы как параметры, какой трюк вы используете для реализации понимания Python как в Java?
У меня есть список (ArrayList) строк. Мне нужно преобразовать каждый элемент, используя функцию, чтобы получить другой список. У меня есть несколько функций, которые берут строку в качестве входных данных и возвращают другую строку в качестве вывода. Как создать общий метод, которому можно присвоить список и функцию как параметры, чтобы я мог получить список с обработанным элементом. Это невозможно в буквальном смысле, но какой трюк я должен использовать?
Другой вариант - написать новую функцию для каждой меньшей функции строковой обработки, которая просто перебирает весь список, что не так круто.
Ответы
Ответ 1
В принципе, вы создаете функциональный интерфейс:
public interface Func<In, Out> {
public Out apply(In in);
}
а затем передать анонимный подкласс вашему методу.
Ваш метод может либо применить функцию к каждому элементу на месте:
public static <T> void applyToListInPlace(List<T> list, Func<T, T> f) {
ListIterator<T> itr = list.listIterator();
while (itr.hasNext()) {
T output = f.apply(itr.next());
itr.set(output);
}
}
// ...
List<String> myList = ...;
applyToListInPlace(myList, new Func<String, String>() {
public String apply(String in) {
return in.toLowerCase();
}
});
или создать новый List
(в основном создавая сопоставление из списка ввода в список вывода):
public static <In, Out> List<Out> map(List<In> in, Func<In, Out> f) {
List<Out> out = new ArrayList<Out>(in.size());
for (In inObj : in) {
out.add(f.apply(inObj));
}
return out;
}
// ...
List<String> myList = ...;
List<String> lowerCased = map(myList, new Func<String, String>() {
public String apply(String in) {
return in.toLowerCase();
}
});
Какой из них предпочтительнее, зависит от вашего варианта использования. Если ваш список чрезвычайно велик, решение на месте может быть единственным жизнеспособным; если вы хотите применить много разных функций к одному и тому же исходному списку, чтобы сделать много списков производных, вам понадобится версия map
.
Ответ 2
В Java 8 вы можете использовать ссылки на методы:
List<String> list = ...;
list.replaceAll(String::toUpperCase);
Или, если вы хотите создать новый экземпляр списка:
List<String> upper = list.stream().map(String::toUpperCase).collect(Collectors.toList());
Ответ 3
Библиотека коллекций Google имеет множество классов для работы с коллекциями и итераторами на гораздо более высоком уровне, чем простая поддержка Java, а также в функциональном способ (фильтр, карта, сгиб и т.д.). Он определяет интерфейсы функций и предикатов и методы, которые используют их для обработки коллекций, поэтому вам не нужно. Он также имеет удобные функции, которые делают работу с Java-дженериками менее сложной.
Я также использую Hamcrest ** для фильтрации коллекций.
Две библиотеки легко сочетаются с классами адаптеров.
** Заявление о заинтересованности: я написал в соавторстве Hamcrest
Ответ 4
Apache Commons CollectionsUtil.transform(Collection, Transformer) - еще один вариант.
Ответ 5
Я создаю этот проект для написания списков в Java, теперь это доказательство концепции в https://github.com/farolfo/list-comprehension-in-java
Примеры
// { x | x E {1,2,3,4} ^ x is even }
// gives {2,4}
Predicate<Integer> even = x -> x % 2 == 0;
List<Integer> evens = new ListComprehension<Integer>()
.suchThat(x -> {
x.belongsTo(Arrays.asList(1, 2, 3, 4));
x.is(even);
});
// evens = {2,4};
И если мы хотим каким-то образом преобразовать выходное выражение, например
// { x * 2 | x E {1,2,3,4} ^ x is even }
// gives {4,8}
List<Integer> duplicated = new ListComprehension<Integer>()
.giveMeAll((Integer x) -> x * 2)
.suchThat(x -> {
x.belongsTo(Arrays.asList(1, 2, 3, 4));
x.is(even);
});
// duplicated = {4,8}
Ответ 6
Вы можете использовать lambdas для функции, например:
class Comprehension<T> {
/**
*in: List int
*func: Function to do to each entry
*/
public List<T> comp(List<T> in, Function<T, T> func) {
List<T> out = new ArrayList<T>();
for(T o: in) {
out.add(func.apply(o));
}
return out;
}
}
использование:
List<String> stuff = new ArrayList<String>();
stuff.add("a");
stuff.add("b");
stuff.add("c");
stuff.add("d");
stuff.add("cheese");
List<String> newStuff = new Comprehension<String>().comp(stuff, (a) -> { //The <String> tells the comprehension to return an ArrayList<String>
a.equals("a")? "1":
(a.equals("b")? "2":
(a.equals("c")? "3":
(a.equals("d")? "4": a
)))
});
вернется:
["1", "2", "3", "4", "cheese"]