Есть такой код
List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");
strings.forEach(string -> System.out.println(string));
Непонятно как он работает, за исключением того, что знаю что лямбда работает по той причине, что интерфейс Consumer является функциональным интерфейсом.
Но вот остальное как то очень запутанно. Возможно вся проблема в том, что у меня сложности в понимании следующего выражения находящиеся в интерфейсе Iterable
default void forEach(Consumer<? super T> action) {/*содержание тела метода
мне понятна, поэтому не
скопировал тут*/}
Просьба: Будет очень полезно, если пошагово напишите алгоритм работы данного кода.
Внимание: Если данный вопрос вдруг оказался дубликатом, тогда просто вставьте ссылку в комментах, без негативных голосов. Если содержание ссылки дает исчерпывающий ответ, тогда я свой вопрос удалю.
Поясняю, метод forEach()
в качестве аргумента принимает функциональный интерфейс
, а именно интерфейс Consumer<T>
. Функциональный интерфейс - это интерфейс, который имеет только один метод. Для чего они нужны? В основном для лямбда-выражений. Итак, структура данного функционального интерфейса представлена следующим образом:
То есть, данный интерфейс принимает какой-то агрумента типа T
и ничего не возвращает (void
). Так же у него есть только один метод - accept()
. Для "активации" нашего действия необходимо вызвать метод accept()
, который нам бы пришлось реализовывать, например, с помощью анонимного класса, например вот так:
Consumer<T> cons = new Consumer<>() {
public void accept(T arg){
System.out.println(arg);
}
}
Согласитесь, не очень удобно каждый раз создавать анонимный класс. Но к нашему счастью лямбда-выражения освобождают нас от этой рутины. Чтобы выполнить этот метод нам достаточно просто написать: s -> System.out.println(s)
. Где s
- это аргумент, который мы передаем в наш фантомный метод accept()
, а System.out.println(s)
-
это то действие, которые мы выполняем в этом методе accept()
. Кстати, гораздо проще передать ссылку на метод: forEach(System.out::println)
. В этом случае каждая перебранная переменная автоматические становится аргументом, который мы передаем в метод accept()
и для каждой мы выполняем метод System.out.println()
.
Use the Source, Luke
Первоисточник достаточно ясно показывает дефолтную имплементацию, а именно:
public interface Iterable<T> {
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
}
Грубо говоря, в кишках сидит конструкция for-each
, которая работает через:
for (Iterator<T> t = iterable.iterator(); t.hasNext();) {
T item = t.next();
//blah-blah
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Сколько бы примеров и полей с датами на Java я не видел, всегда (или почти всегда) используют класс DateПри этом, я думаю, всем известно, что класс...
У меня есть простой браузерМне надо чтобы в нём открывались ссылки, как например в Google Chrome
Я получаю уведомления в панели разработчика что в приложении происходят сбои, а именно IllegalArgumentExeption на 9 Андроиде по большей части на устройствах...