Стримы java. Стримы. 1 Функциональные интерфейсы, основные типы
Скачать 149.5 Kb.
|
41) Чем является Stream в контексте Java? Обработчик потоков объекта Поток представляет собой последовательность элементов и поддерживает различные виды операций для выполнения вычислений: Большинство операций потока принимают в качестве параметров какие-то лямбда-выражения, в функциональный интерфейс точное поведение по каждой операции. Большинство этих операций должны быть как неинтерферирующими (non-interfering), так и лишенными состояния (stateless). Что это значит? Неинтерферирующуя функция не изменяет основной источник данных потока. Например, в приведенном выше примере лямбда выражение не изменяет mList путем добавления или удаления элементов из коллекции. Лишенная состояния функция — выполнение операции является детерминированным, например, в приведенном выше примере лямбда-выражение не зависит от какой-либо изменяемой переменной или состояния из внешней среды, которая могла бы измениться во время выполнения. 42) В каком пакете находится Stream? Средства работы с потоками данных Stream API являются составляющей пакета java.util.stream. Данный пакет содержит набор потоковых интерфейсов, образующих иерархию. Базовым поточным интерфейсом является BaseStream. 43) Чем Stream отличается от итератора? Итератор это простой обьект который умеет выдовать только один элемент по одному Стрим гораздо сложный и навароченный, у него огромное количество методлов он содержит не только средства обхода элементов 1) описания 2) обработки 3) преобразования последовательности элементов 44) Сравнение стримов с коллекцией коллекции предпологают хранение элементов и соответственно конечны Стримы бесконечны коллекции часто предоставляют индивидуальный доступ(индекс, ключ) Стрим такого не позволяет колекции можно менять, добавлять либо удалять элементы в том числе через итератора А применение трансформации к Стриму, ни как не влияют на источник откуда берется информация 45) Из каких частей состоит использование стримов? 1) получение Стрима откуда будут браться элементы последовательно 2) Ноль или более промежуточных преобразований. Стрим их запоминате но пока не выполняет 3) Единственная терминальная иоперация запускающая вес процесс вычесления и которая должна стать его полезным результатом. 4) Закрытие стрима вызвать метод Close, обязателен только в том случае, когда стрим выделял какието системные ресурсы.(файл, потоки) можно использовать в с трай ресурсами 46) В каком случае нужно закрывать стрим? 4) Закрытие стрима вызвать метод Close, обязателен только в том случае, когда стрим выделял какието системные ресурсы.(файл, потоки) можно использовать в с трай ресурсами 47) Первый этап работы со стримом 48) Откуда можно получить стрим? Получить стрим можно из любой коллекции с помощью стрим или получить из потока, с помощью метода lines(); Из дерриктории на диске с пмомощью list(), walk(); Получить из строчки с помощью метода shars() Стримы можно пораждать динамически Например с помощью Supplier, который имеет один метод get() Итерирование какойто функции Диапазон в виде стрема 1) от начало диапазона до конца не в ключительно(0 - 99) 2) от начала до конца включительно(0 - 100) Конкатенации двух других Стримов Или взять пустой стрим из массива указать явно 1) Из коллекции: Stream Стрим из List: list.stream() Стрим из Map: map.entrySet().stream() 2) Из набора значений: Stream 3) Из массива: Stream 4) Из файла (каждая строка в файле будет отдельным элементом в стриме): Stream 5) Из строки: IntStream fromString = "0123456789".chars(); 6) С помощью Stream.builder(): Stream 7) С помощью Stream.iterate() (бесконечный): Stream 8) С помощью Stream.generate() (бесконечный): Stream 9) Создание паралельного стрима collection.parallelStream() Stream 49) Терминальные и промежуточные методы. 50) Разница методов .list() и walk() Что такое саплер-поставщик? какой содержит метод? Как динамически получать стрим? Files.list() возвращает массив файлов в указанной директории Files.walk() возвращает поток файлов в указанной директории и субдиректориях Из опыта скажу, что list(); метод подразумевает когда мы указываем ему, где нужно проходить List возвращает список либо String либо File А метод walk(); сам идет в поддериктории ему просто надо указать на какую глубину нужно идти прогулка walk(); public static Stream walk(Path start, FileVisitOption... options) throws IOException DoubleStream doubleStream = DoubleStream.generate(Math::random);//сеплаер поставщик Supplier (с англ. — поставщик) — функциональный интерфейс, который не принимает никаких аргументов, но возвращает некоторый объект типа T: который представляет собой оператор, предоставляющий значение для каждого вызова. Supplier имеет только один метод get() и не имеет метода по умолчанию. Supplier IntSupplier int getAsInt(); DoubleSupplier double getAsDouble(); LongSupplier long getAsLong(); BooleanSupplier boolean getAsBoolean(); 60) 61) Как получить стрим диапазона чисел? IntStream smalInteger = IntStream.range(0, 100);//из диапазона IntStream smallInteger2 = IntStream.rangeClosed(0, 100); 62) В чем разница методов range и rangeClosed? в том, что первый не выдает последний элемент а второй выдает. 63) Можно ли конкатенировать стримы? если да то каким методом? Можно ли получить пустой стрим? да можно! IntStream cobiedStream = IntStream.concat(stream1,stream2);//конкатенация IntStream empty = IntStream.empty();//пустой стрим взять 64) Отличия Абстрактного класса от интерфейса Фундаментальная разница между интерфейсом и абстрактным классом заключается в том, что интерфейс определяет только поведение. Он не сообщает ничего про объект, который будет его реализовывать. Например, такое поведение как «движение» может быть применимо к разным типам объектов: машина, кот, котировки курса и т. д. Эти объекты не имеют ничего общего, кроме того, что они могут двигаться. Перефразируем немного иначе — если существует «движущийся» объект, то глядя на реализованный им интерфейс, мы не сможем понять, какой именно тип объекта имеется ввиду. Это может быть машина, кот, котировка курса валют и много других вариантов. Если перенести это поведение в код, написанный на языке Java, то получится следующее: interface Movable { void move(); } Абстрактный же класс описывает некий абстрактный объект (автомобиль, человека, кота и т. д.), а не только поведение. Если мы рассуждаем про абстрактный «автомобиль», то в нашей голове сразу формируется картинка с объектом. Мы сразу понимаем, что автомобиль содержит двигатель, колеса и может двигаться, поворачивать, ускоряться или тормозить. Он также будет иметь поля для хранения внутренних деталей, таких как мотор, колеса и тормоза. Вы получите все это просто сказав слово «автомобиль». При этом кот и котировка курса валют не могут быть автомобилем, даже если они также могут двигаться. 65) Как получить стрим из массива? double[] array = ...; DoubleStream doubleStream1 = Arrays.stream(array);//или из массива 66) Какой второй этап работы со стримом? Применение промежуточных методов. //в качестве промежуточной операции можно встроить peek(Consuver) с помощью него можно посмотреть какие объекты летают на разных этапах обработки для отладки можно передовать System.out::println 67) Перечислить основные промежуточные операции. Их предназначение. Map() - Любое изменение исходного элемента можно делать с помощью метода map(). В качестве параметра метод принимает лямбда-выражение. filter() - Отсеивание части объектов sorted() - peek()- доступ к элементу, не изменяя его, например вывести лог. flatMap() - skip() пропустить эл. limit() ограничивает оставшиеся элементы 68) Для чего терминальные операции? Какие бывают и что делают? Терминальные (“terminal”, ещё называют “eager”) — обрабатывают элементы и завершают работу стрима, так что терминальный оператор в цепочке может быть только один. findFirst Возвращает первый элемент из стрима (возвращает Optional) collection.stream().findFirst().orElse(«1») findAny Возвращает любой подходящий элемент из стрима (возвращает Optional) collection.stream().findAny().orElse(«1») collect Представление результатов в виде коллекций и других структур данных collection.stream().filter((s) -> s.contains(«1»)).collect(Collectors.toList()) count Возвращает количество элементов в стриме collection.stream().filter(«a1»::equals).count() anyMatch Возвращает true, если условие выполняется хотя бы для одного элемента collection.stream().anyMatch(«a1»::equals) noneMatch Возвращает true, если условие не выполняется ни для одного элемента collection.stream().noneMatch(«a8»::equals) allMatch Возвращает true, если условие выполняется для всех элементов collection.stream().allMatch((s) -> s.contains(«1»)) min Возвращает минимальный элемент, в качестве условия использует компаратор collection.stream().min(String::compareTo).get() max Возвращает максимальный элемент, в качестве условия использует компаратор collection.stream().max(String::compareTo).get() forEach Применяет функцию к каждому объекту стрима, порядок при параллельном выполнении не гарантируется set.stream().forEach((p) -> p.append("_1")); forEachOrdered Применяет функцию к каждому объекту стрима, сохранение порядка элементов гарантирует list.stream().forEachOrdered((p) -> p.append("_new")); toArray Возвращает массив значений стрима collection.stream().map(String::toUpperCase).toArray(String[]::new); reduce Позволяет выполнять агрегатные функции на всей коллекцией и возвращать один результат collection.stream().reduce((s1, s2) -> s1 + s2).orElse(0) Обратите внимание методы findFirst, findAny, anyMatch это short-circuiting методы, то есть обход стримов организуется таким образом чтобы найти подходящий элемент максимально быстро, а не обходить весь изначальный стрим. Краткое описание терминальных методов работы со стримами findFirst Возвращает первый элемент из стрима (возвращает Optional) collection.stream().findFirst().orElse(«1») findAny Возвращает любой подходящий элемент из стрима (возвращает Optional) collection.stream().findAny().orElse(«1») collect Представление результатов в виде коллекций и других структур данных collection.stream().filter((s) -> s.contains(«1»)).collect(Collectors.toList()) 69) Что такое коллекторы? collect(). Он используется для того, чтобы перейти от потоков к привычным коллекциям — List В метод collect() нужно передать специальный объект — collector. Этот объект вычитывает все данные из потока, преобразует их к определенной коллекции и возвращает ее. А следом за ним эту же коллекцию возвращает и сам метод collect. Все это сделано довольно хитро: объект collector имеет тип Collector Последний тип R — это обычно и есть тип вроде List Поэтому компилятор может по этому типу подставить правильный тип результата самого метода collect(). toList() Объект, который преобразует поток в список — List toSet() Объект, который преобразует поток во множество — Set toMap() Объект, который преобразует поток в мэп — Map joining() Склеивает элементы потока в одну строку mapping() Преобразует элементы потока в Map groupingBy() Группирует элементы, возвращает Map 70) Сколько раз можно вызывать терминльную операцию? Один раз. 71) Что такое метод референс? 1. Если лямбда выражения вызывают только один существующий метод, лучше ссылать на этот метод по его имени. Ссылки на методы (Method References) – это компактные лямбда выражения для методов у которых уже есть имя. 2. Ссылка на статический метод 3. Ссылка на нестатический метод конкретного объекта 4. Ссылка на нестатический метод любого объекта конкретного типа 5. Ссылка на конструктор ContainingClass::staticMethodName Ссылка на статический метод containingObject::instanceMethodName Ссылка на нестатический метод конкретного объекта ContainingType::methodName Ссылка на нестатический метод любого объекта конкретного типа ClassName::new Ссылка на конструктор 72) В чем разница между foreach и foreachordered void forEach(Consumer action) - выполняет указанное действие для каждого элемента стрима. void forEachOrdered(Consumer action) - Тоже выполняет указанное действие для каждого элемента стрима, но перед этим добивается правильного порядка вхождения элементов. Используется для параллельных стримов, когда нужно получить правильную последовательность элементов. 73) Как можно классифицировать стримы в разных контекстах? 74) Что такое default методы в интерфейсе и для чего они были введены? 75) как взаимосвязаны лямбда и функциональный интерфейс? Лямбда это возможность замены вызова реализации интерфейса с одним методом. Лямбдой вырожением мы просто более компактно записываем вызов метода функционального интерфейса с одним методом 76) Что такое ленивая инициализация стрима? 77) Любой анонимный класс можно заменить на лямбду? класс в котором есть один метод, можно заменить на лямбду 78) Расскажите про Comparator и Comparable? 79) Все способы реализации функционального интерфейса? 4 способа 80) Приведи пример терминальной и промежуточной операции над стримом? 81) В чем разница map и flatMap? И map и flatMap могут быть применены к стриму Stream что операция map создает одно выходное значение для каждого входного значения, тогда как операция flatMap создает произвольное число(ноль или больше) значений для каждого входного значения. Операция map(О работе map на русском) в качестве аргумента принимает Function(например, лямбду), которая вызывается для каждого значения входного стрима(который и посылает получившееся значение в выходной стрим(который Т.е. map для каждого объекта в стриме возвращает по 1 объекту, потом преобразует все объекты в итоговый стрим. Операция flatMap(О работе flatMap на русском) принимает функцию (которая преобразует каждое значение входного стрима в стрим), применяет ее к каждому элементу, и на выходе возвращает стрим с одним, несколькими или ни c одним из элементов для каждого элемента входящего стрима. Т.е., flatMap возвращает по стриму для каждого объекта в первоначальном стриме, а затем результирующие потоки объединяются в исходный стрим. Оба map и flatMap могут быть применены к Stream что операция map создает одно выходное значение для каждого входного значения, тогда как операция flatMap производит произвольное число (ноль или более) значений для каждого входного значения. Это отражается в аргументах каждой операции. Операция map занимает Function, которая вызывается для каждого значения во входном потоке и выдает одно значение результата, которое отправляется в выходной поток. Операция flatMap принимает функцию, которая концептуально хочет потреблять одно значение и производить произвольное количество значений. Однако в Java это громоздко для метода для возврата произвольного количества значений, поскольку методы могут возвращать только ноль или одно значение. Можно представить API, в котором функция mapper для flatMap принимает значение и возвращает массив или List значений, которые затем отправляются на выход. Учитывая, что это библиотека потоков, особенно подходящим способом представления произвольного количества возвращаемых значений является то, что сама функция mapper возвращает поток! Значения из потока, возвращаемого преобразователем, выводятся из потока и передаются в выходной поток. "Сгустки" значений, возвращаемых каждым вызовом функции сопоставления, вообще не различаются в выходном потоке, поэтому выход считается "сплющенным". Типичное использование функции mapper flatMap для возврата Stream.empty(), если оно хочет отправить нулевые значения или что-то вроде Stream.of(a, b, c), если оно хочет вернуть несколько значений. Но, конечно, любой поток может быть возвращен. 82) Зачем нужны default методы в функциональном интерфейсе - тут про обратную совместимость. 83) Все способы реализации фун.инт: 4 штуки: ссылка на метод, лямбда, через анонимный класс, через обычную имплементацию в классе. 84) к каким переменным можно обращаться внутри лямбды: переменные внутри метода (эффективно-финальные), static переменные класса, переменные интерфейса (с которым лямбда работает)? 85) ссылка на метод - ну и в каком виде передается: имя класса:: имя стат метода (для статического метода); объект класса:: имя метода (для метода экземпляра); название класса:: new(для конструктора) 86) как получить стрим - через разные метод бесконечные стримы ( через iterate и generate) 87) Какие бывают стримы: знать 3 группы: 1) конечные и бесконечные, 2) последовательные и параллельные 3) объектные и примитивные спрашивает про параллельные, промежуточные и терминальные (конечные и бесконечные это) 88) Знать 5 примеров промежуточных операций (intermediate методы) и знать 5 примеров терминальных операций 89) Расспрашивает про терминальные и промежуточные: кто такие, сколько раз нужно вызывать, где вызывать, терминальные нужны (начало-конец?) 90) что возвращают промежуточные операции: stream 91) для чего нужны методы forEach() и forEachOrdered() Возможный вариант использования потока может состоять в том, чтобы обновить свойство некоторых или всех элементов или почему бы просто не распечатать их для целей отладки. В любом случае, мы не заинтересованы в сборе или подсчете результата, а скорее в создании побочного эффекта без возврата значения. Это цель forEach() или forEachOrdered() . Они оба принимают Consumer и прекращает поток, не возвращая ничего. Разница между этими операциями просто в том, что forEachOrdered() обещает вызвать предоставленного forEachOrdered() в порядке появления элементов в потоке, тогда как forEach() только обещает вызвать Потребителя, но в любом порядке. Последний вариант полезен для параллельных потоков. В простом случае, приведенном ниже, мы распечатываем каждый элемент потока в одну строку. Stream.of( "Monkey", "Lion", "Giraffe", "Lemur", “Lion” ) .forEachOrdered(System.out::print); Это даст следующий результат: MonkeyLionGiraffeLemurLion 92) В чем разница между интерфейсами Comparable и Comparator? 93) еще методы peek и forEach - в чем разница: первый промежуточный, второй - терминальный, ну и функционал какой у каждого 94) функциональное программирование- плюсы минусы, где применяется 95) анонимные классы, как создать, где применяются, особенно как создать экземпляр. это локальный класс без имени. Используется тогда, когда нужно переопределить метод класса или интерфейса. как статический либо как нестатический вложенный класс - в нестатическом контексте появляется окружающий его экземпляр. Анонимные классы позволяют сделать наш код более кратким. Анонимные классы позволяют одновременно объявить класс и создать его экземпляр. Анонимные классы, в отличие от локальных, не имеют имени. Используйте анонимные классы, если локальный класс нужен вам единожды. Как уже говорилось, объявление анонимных классов происходит внутри выражения. Синтаксис анонимных классов похож на вызов конструктора класса, за исключением того, что происходит определение класса. Анонимный класс — это полноценный внутренний класс. Поэтому у него есть доступ к переменным внешнего класса, в том числе к статическим и приватным: И еще одно важное ограничение, которое досталось анонимным классам от их «предков» — внутренних классов: анонимный класс не может содержать статические переменные и методы. Добустим у нас есть интерфейс с тремя методами Что бы их реализовать мы можем создать полноценные классы это долго и многословно. Есть вариант создать анонимные безимянные классы. Например создаем типо объект интерфейса(но не объект, объект интерфейса создавать нельзя) Пример MyInterfes testInterfeys = new MyInterfes(){ @overaid }; 96) Objects (зачем нужен) 97) Все способы реализации функицональных интерфейсов 4 штуки 1) Имплемитирование в клас 2) вызов метода 3) лямбда выражение 4) вызов через конструктор 98) К каким переменным есть доступ из лямбда-выражения 99) Инстанцировать Это создание экземпляра класса 100) Эффективно финальными 101) Минусы Стрима 102) |