diff --git a/Part 1 - Getting Started/1. Why Rx.md b/Part 1 - Getting Started/1. Why Rx.md index 5ea1fff..172298b 100644 --- a/Part 1 - Getting Started/1. Why Rx.md +++ b/Part 1 - Getting Started/1. Why Rx.md @@ -2,7 +2,7 @@ ## Почему Rx? -> Пользователи ожидают данных в реальном времени. Они хотят твиты сейчас. Подтвержение заказа сейчас. Им необходимы цены по состоянию на сейчас. Как разработчик, вы нуждаетесь в самонаводящихся сообщениях. Вы не хотите быть блокированным в ожидании результата. Вы хотите, чтобы результат пришел к вам по готовности. Даже более того, вы хотите работать с результатом по частям: вы не хотите ждать пока загрузится всё перед тем как отобразить первую строку. Мир перешел в режим уведомлений. У разработчиков есть инструменты, чтобы уведомлять, это легко. Им нужны инструменты чтобы реагировать на уведомления. +> Пользователи ожидают данных в реальном времени. Они хотят твиты сейчас. Подтверждение заказа сейчас. Им необходимы цены по состоянию на сейчас. Как разработчик, вы нуждаетесь в самонаводящихся сообщениях. Вы не хотите быть блокированным в ожидании результата. Вы хотите, чтобы результат пришел к вам по готовности. Даже более того, вы хотите работать с результатом по частям: вы не хотите ждать пока загрузится всё перед тем как отобразить первую строку. Мир перешел в режим уведомлений. У разработчиков есть инструменты, чтобы уведомлять, это легко. Им нужны инструменты чтобы реагировать на уведомления. Добро пожаловать в Rx. Rx – это мощный инструмент, который позволяет решать проблемы в элегантном декларативном стиле, присущем функциональному программированию. Rx обладает следующими преимуществами: @@ -11,7 +11,7 @@ * Расширяемость * RxJava может быть расширена пользовательскими операторами. И хотя Java не позволяет сделать это элегантным образом, RxJava предлагает всю расширяемость доступную в реализациях Rx на любом другом языке. * Декларативность - * Функциональные трансформации обьявлены декларативно. + * Функциональные трансформации объявлены декларативно. * Компонуемость * Операторы в Rx легко компонуются, чтобы проводить сложные операции. * Преобразуемость @@ -27,7 +27,7 @@ Rx применяется для составления и обработки п * UI события, такие как mouse move, button click * События вроде изменения свойства, обновления коллекции, «Заказ оформлен», «Регистрация закончена» и т.д. * Инфраструктурные события (сообщения от системы, WMI или файловых менеджеров) -* Интеграция с событиями от шины сообщений (message bus), сообщениями из WebScoket API +* Интеграция с событиями от шины сообщений (message bus), сообщениями из WebSocket API * Интеграция с [CEP-системами](https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D1%81%D0%BB%D0%BE%D0%B6%D0%BD%D1%8B%D1%85_%D1%81%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B9) (StreamInsight, StreamBas) ### Возможно использование Rx diff --git a/Part 1 - Getting Started/2. Key types.md b/Part 1 - Getting Started/2. Key types.md index 0bb0260..d93424b 100644 --- a/Part 1 - Getting Started/2. Key types.md +++ b/Part 1 - Getting Started/2. Key types.md @@ -35,10 +35,10 @@ interface Observer { ``` Эти три метода являются поведением, которое описывает реакцию наблюдателя на сообщение от observable. onNext у наблюдателя будет вызван 0 или более раз, опционально сопровождаясь onCompleted или onError. После них вызовов больше не будет. -Разрабатывая код с помощью Rx, вы увидите много Observable, но намного меньше Observer. И хотя и необходимо понимать концепцию Observer, существуют способы не требующие непосредственного создания его экземпляра. +Разрабатывая код с помощью Rx, вы увидите много Observable, но намного меньше Observer. И хотя и необходимо понимать концепцию Observer, существуют способы, не требующие непосредственного создания его экземпляра.

Реализация Observable и Observer

-Вы можете вручную реализовать Observer и Observable. В реальности в этом, как правило, нет необходимости: Rx предоставляет готовые решения, чтобы упростить разработку. Это также может быть не совсем безопасно, поскольку взаимодействие между частями библиотеки Rx включает в себя принципы и внутреннюю инфраструктуру, которые могут быть не очевидны новичку. В любом случае, будет проще для начала использовать множество инструментов уже предоставленных библиотекой для создания необходимого нам функционала. +Вы можете вручную реализовать Observer и Observable. В реальности в этом, как правило, нет необходимости: Rx предоставляет готовые решения, чтобы упростить разработку. Это также может быть не совсем безопасно, поскольку взаимодействие между частями библиотеки Rx включает в себя принципы и внутреннюю инфраструктуру, которые могут быть неочевидны новичку. В любом случае, будет проще для начала использовать множество инструментов, уже предоставленных библиотекой для создания необходимого нам функционала. Чтобы подписаться на observable, совсем нет необходимости в реализации Observer. Существуют другие перегрузки метода subscribe, которые принимают в качестве аргументов соответствующие функции для onNext, onError и onSubscribe, инкапсулирующие создание экземпляра Observer. Предоставлять их всех тоже не обязательно, вы можете описать только часть из них, например, только onNext или только onNext и onError. @@ -68,17 +68,17 @@ public static void main(String[] args) { 3 4 ``` -Как мы видим, 1 не была напечатана из-за того, что мы не были подписаны в момент когда она была передана. После того как мы подписались, мы начали получать все значения поступающие в subject. +Как мы видим, 1 не была напечатана из-за того, что мы не были подписаны в момент, когда она была передана. После того как мы подписались, мы начали получать все значения, поступающие в subject. -Здесь мы впервые используем метод subscribe, так что стоит уделить этому внимание. В данном случае мы используем перегруженную версию, которая принимает один объект класса Function, отвечающий за onNext. Эта функция принимает значение типа Integer и ничего не возвращает. Функции, которые ничего не возвращают также называются actions. Мы можем передать эту функцию следующими способами: +Здесь мы впервые используем метод subscribe, так что стоит уделить этому внимание. В данном случае мы используем перегруженную версию, которая принимает один объект класса Function, отвечающий за onNext. Эта функция принимает значение типа Integer и ничего не возвращает. Функции, которые ничего не возвращают, также называются actions. Мы можем передать эту функцию следующими способами:

ReplaySubject

-ReplaySubject имеет специальную возможность кэшировать все поступившие в него данные. Когда у него появляется новый подписчик, последовательность выдана ему начиная с начала. Все последующие поступившие данные будут выдаваться подписчикам как обычно. +ReplaySubject имеет специальную возможность кэшировать все поступившие в него данные. Когда у него появляется новый подписчик, последовательность выдается ему, начиная с начала. Все последующие поступившие данные будут выдаваться подписчикам как обычно. ```JAVA ReplaySubject s = ReplaySubject.create(); @@ -97,9 +97,9 @@ Late: 1 Early:2 Late: 2 ``` -Все значения были получены, не смотря на то, что один из подписчиков подписался позже другого. Обратите внимание, что до того как получить новое значение, подписчик получает все пропущенные. Таким образом, порядок последовательности для подписчика не нарушен. +Все значения были получены, несмотря на то, что один из подписчиков подписался позже другого. Обратите внимание, что до того как получить новое значение, подписчик получает все пропущенные. Таким образом, порядок последовательности для подписчика не нарушен. -Кэшировать всё подряд не всегда лучшая идея, так как последовательности могут быть длинными или даже бесконечными. Фабричный метод ReplaySubject.createWithSize ограничивает размер буфера, а ReplaySubject.createWithTime время, которое объекты будут оставаться в кеше. +Кэшировать всё подряд не всегда лучшая идея, так как последовательности могут быть длинными или даже бесконечными. Фабричный метод ReplaySubject.createWithSize ограничивает размер буфера, а ReplaySubject.createWithTime время, которое объекты будут оставаться в кэше. ```JAVA ReplaySubject s = ReplaySubject.createWithSize(2); @@ -166,10 +166,10 @@ s.onNext(1); 0 1 ``` -Так как роль BehaviorSubject – всегда иметь доступные данные, считается неправильным создавать его без начального значения, также как и завершать его. +Так как роль BehaviorSubject – всегда иметь доступные данные, считается неправильным создавать его без начального значения так же, как и завершать его.

AsyncSubject

-AsyncSubject также хранит последнее значение. Разница в том, что он не выдает данных до тех пока не завершится последовательность. Его используют, когда нужно выдать единое значение и тут же завершиться. +AsyncSubject также хранит последнее значение. Разница в том, что он не выдает данных до тех пор, пока не завершится последовательность. Его используют, когда нужно выдать единое значение и тут же завершиться. ```JAVA AsyncSubject s = AsyncSubject.create(); @@ -186,7 +186,7 @@ s.onCompleted(); Обратите внимание, что если бы мы не вызвали s.onCompleted(), этот код ничего бы не напечатал.

Неявная инфраструктура

-Как мы уже упоминали, существуют принципы, которые могут быть не очевидны в коде. Один из важнейших заключается в том, что ни одно событие не будет выдано после того, как последовательность завершена (onError или onCompleted). Реализация subject’ уважает эти принципы: +Как мы уже упоминали, существуют принципы, которые могут быть неочевидны в коде. Один из важнейших заключается в том, что ни одно событие не будет выдано после того, как последовательность завершена (onError или onCompleted). Реализация subject’ уважает эти принципы: ```JAVA Subject s = ReplaySubject.create(); @@ -205,7 +205,7 @@ s.onNext(2); notes [1] Или знакомые всем Event Listeners. – Примеч. Автора [2] Я, все-таки считаю, что ключевой перегрузкой тут является именно версия с Observer в качестве аргумента, в оригинале в качестве примера приводится версия subscribe(Subscriber subscriber) – Примеч. Автора -[3] Я буду использовать слово «выдавать» чтобы описать событие передачи данных от Observable Observer’у (to emit в ориг.). – Примеч. Автора +[3] Я буду использовать слово «выдавать», чтобы описать событие передачи данных от Observable Observer’у (to emit в ориг.). – Примеч. Автора [4] Автор использует термин последовательность (sequence), чтобы обозначить множество всех данных, которые может выдать Observable. – Примеч. Автора #### Продолжить чтение diff --git a/Part 2 - Sequence Basics/1. Creating a sequence.md b/Part 2 - Sequence Basics/1. Creating a sequence.md index ced9f83..376edb8 100644 --- a/Part 2 - Sequence Basics/1. Creating a sequence.md +++ b/Part 2 - Sequence Basics/1. Creating a sequence.md @@ -1,6 +1,6 @@ # Часть 2 - Основы последовательностей -Теперь, когда мы понимаем основные принципы Rx, настало время научиться создавать и управлять последовательностями. Стиль управления последовательностями был позаимствован у оригинального C# [LINQ](https://en.wikipedia.org/wiki/Language_Integrated_Query), который в свою очередь был вдохновлен функциональным программироанием. Мы поделим все операции по темам, которые отсортированы в порядке возрастания сложности операций. Большинство операторов Rx управляют уже существующими последовательностями, но для начала мы научимся их создавать. +Теперь, когда мы понимаем основные принципы Rx, настало время научиться создавать и управлять последовательностями. Стиль управления последовательностями был позаимствован у оригинального C# [LINQ](https://en.wikipedia.org/wiki/Language_Integrated_Query), который в свою очередь был вдохновлен функциональным программированием. Мы поделим все операции по темам, которые отсортированы в порядке возрастания сложности операций. Большинство операторов Rx управляют уже существующими последовательностями, но для начала мы научимся их создавать. # Создание последовательности @@ -59,7 +59,7 @@ Subscription subscription = values.subscribe( ); ``` -Код [выше](/tests/java/itrx/chapter2/creating/ObservableFactoriesExample.java) ничего не напечатает. Но это не означает что программа блокируется. По-факту она просто мгновенно завершается. +Код [выше](/tests/java/itrx/chapter2/creating/ObservableFactoriesExample.java) ничего не напечатает. Но это не означает что программа блокируется. По факту она просто мгновенно завершается. ### Observable.error @@ -95,7 +95,7 @@ now.subscribe(System.out::println); 1431443908375 ``` -Обратите внимание как второй подписчик, подписавшись на секунду позже, получил такое же время. Это происходит потому что значение времени было вычислено лишь единажды: когда выполнение доходит до метода `just`. Однако в нашем случае мы хотим вычислять текущее время при каждой подписке. `defer` принимает функцию, которая возвращает `Observable` и будет выполнена для каждого нового подписчика. +Обратите внимание как второй подписчик, подписавшись на секунду позже, получил такое же время. Это происходит потому что значение времени было вычислено лишь единожды: когда выполнение доходит до метода `just`. Однако в нашем случае мы хотим вычислять текущее время при каждой подписке. `defer` принимает функцию, которая возвращает `Observable` и будет выполнена для каждого нового подписчика. ```java Observable now = Observable.defer(() -> @@ -140,9 +140,9 @@ Completed Когда кто-нибудь подпишется на наш `Observable` (в данном случае `values`), соответствующий экземпляр `Subscriber` будет передан в функцию `create`. По мере выполнения кода, значения будут переданы подписчику. Следует обратить внимание, что нужно самостоятельно вызывать метод `onCompleted` чтобы просигнализировать окончание последовательности. -Данный метод является рекомендуемым способом создания `Observable` в случае если ни один из других способов не подходит. Это похоже на то, как мы создавали `Subject` и вручную подавали на него значения, однако есть несколько важных отличий. В первую очередь, источних событий аккуратно инкапсулирован и отделен от другого кода. Во-вторых, `Subject`'ы имеют неочевидные опасности: любой кто имеет доступ к обьекту сможет изменить последовательность. Мы еще вернемся к этой проблеме позже. +Данный метод является рекомендуемым способом создания `Observable` в случае если ни один из других способов не подходит. Это похоже на то, как мы создавали `Subject` и вручную подавали на него значения, однако есть несколько важных отличий. В первую очередь, источник событий аккуратно инкапсулирован и отделен от другого кода. Во-вторых, `Subject`'ы имеют неочевидные опасности: любой кто имеет доступ к объекту сможет изменить последовательность. Мы еще вернемся к этой проблеме позже. -Еще одним ключевым отличием от использования `Subject` является то, что код выполняется "lazily", только тогда когда прибывает новый подписчик. В примере выше, код выполняется _не_ в момент создания `Observable` (так как подписчиков еще нет), а в момент вызова метода `subscribe`. Это означает, что значения будет вычислены заново для каждого подписчика, как в `ReplaySubject`. Конечный результат похож на `ReplaySubject`, за исключением кеширования. С помощью `create` мы также можем легко перенести выполнение в отделный поток, в то время как с `ReplaySubject` нам приходилось бы вручную создавать потоки для вычисления значений. Мы еще рассмотрим способы сделать выполнение метода `onSubscribe` параллельным. +Еще одним ключевым отличием от использования `Subject` является то, что код выполняется "lazily", только тогда когда прибывает новый подписчик. В примере выше, код выполняется _не_ в момент создания `Observable` (так как подписчиков еще нет), а в момент вызова метода `subscribe`. Это означает, что значения будет вычислены заново для каждого подписчика, как в `ReplaySubject`. Конечный результат похож на `ReplaySubject`, за исключением кеширования. С помощью `create` мы также можем легко перенести выполнение в отдельный поток, в то время как с `ReplaySubject` нам приходилось бы вручную создавать потоки для вычисления значений. Мы еще рассмотрим способы сделать выполнение метода `onSubscribe` параллельным. Вы уже могли заметить что любой из предыдущих `Observable` можно реализовать при помощи `Observable.create`. Наш пример для `create` эквивалентен `Observable.just("hello")`. @@ -163,7 +163,7 @@ Observable values = Observable.range(10, 15); ### Observable.interval -Эта функция создаст _бесконечную_ последовательность значений, отделенных заданным интервалом времени. +Эта функция создаст _бесконечную_ последовательность значений, разделенных заданным интервалом времени. ```java Observable values = Observable.interval(1000, TimeUnit.MILLISECONDS); @@ -243,7 +243,7 @@ Observable events = Observable.create(o -> { ## Observable.from -Вы можете превратить любые входные данные в `Observable` при помощи `create`. Однако, для распространенных типов данных, существуют уже готовые методы, призваные облегчить этот процесс. +Вы можете превратить любые входные данные в `Observable` при помощи `create`. Однако, для распространенных типов данных, существуют уже готовые методы, призванные облегчить этот процесс. `Future`'ы являются частью Java и вы должно быть сталкивались с ними во время работы с фреймворками использующими многопоточность. Они являются менее мощным многопоточным инструментом чем Rx, так как возвращают только одно значение. Как правило, вы захотите превратить их в `Observable`. @@ -268,7 +268,7 @@ Received: 21 Completed ``` -`Observable` выдает результат `FutureTask` по-готовности, после чего завершается. Если задача была отменена, observable выдаст ошибку `java.util.concurrent.CancellationException`. +`Observable` выдает результат `FutureTask` по готовности, после чего завершается. Если задача была отменена, observable выдаст ошибку `java.util.concurrent.CancellationException`. Если вы заинтересованы в результате `Future` только ограниченное время, существует возможность задать таймаут в качестве аргумента. @@ -277,7 +277,7 @@ Observable values = Observable.from(f, 1000, TimeUnit.MILLISECONDS); ``` Если за это время `Future` не завершится, observable проигнорирует результат и выдаст `TimeoutException`. -С помощью `Observable.from` можно превратить любую коллекцию в последовательность. Будет создан `Observable`, выдающий каждый элемент коллекции по-отдельности и `onCompleted` в конце. +С помощью `Observable.from` можно превратить любую коллекцию в последовательность. Будет создан `Observable`, выдающий каждый элемент коллекции по отдельности и `onCompleted` в конце. ```java Integer[] is = {1,2,3}; diff --git a/Part 2 - Sequence Basics/2. Reducing a sequence.md b/Part 2 - Sequence Basics/2. Reducing a sequence.md index 508fa9f..c5c824c 100644 --- a/Part 2 - Sequence Basics/2. Reducing a sequence.md +++ b/Part 2 - Sequence Basics/2. Reducing a sequence.md @@ -1,18 +1,18 @@ -# Reducing a sequence +# Фильтрация последовательности -The examples we've seen so far were all very small. Nothing should stop you from using Rx on a huge stream of realtime data, but what good would Rx be if it dumped the whole bulk of the data onto you, and force you handle it like you would otherwise? Here we will explore operators that can filter out irrelevant data, or reduce the data to the single value that you want. +Примеры которые мы видели до этого были достаточно малы. Ничто не должно удерживать вас от использования Rx при больших объемах данных, но что хорошего в Rx если он выбросит на вас весь объем данных, и оставит вас разбираться с этим своими силами? Здесь мы разберем операторы которые помогут отфильтровать ненужные данные, или сократить последовательность к единому нужному нам значению. -Most of the operators here will be familiar to anyone who has worked with Java's `Stream`s or functional programming in general. All the operators here return a new observable and do _not_ affect the original observable. This principle is present throughout Rx. Transformations of observables create a new observable every time and leave the original unaffected. Subscribers to the original observable should notice no change, but we will see in later chapters that guaranteeing this may require caution from the developer as well. +Большинство представленных операторов будут знакомы тем кто работал с Java `Stream API` или функциональным программированием. Все операторы возвращают новый объект Observable и _не_ влияют на оригинальный Observable. Этот принцип является ключевым в Rx. Преобразование Observable приводит к созданию нового Observable, оригинальный объект остается незатронутым. Подписчики(Subscribers) оригинального объекта не должны заметить никаких изменений, но как мы увидим дальше гарантирование этого принципа требует также осторожности от разработчика. -### Marble diagrams +### Диаграммы Marble -This is an appropriate time to introduce to concept of marble diagrams. It is a popular way of explaining the operators in Rx, because of their intuitive and graphical nature. They are present a lot in the documentation of RxJava and it only makes sense that we take advantage of their explanatory nature. The format is mostly self-explanatory: time flows left to right, shapes represent values, a slash is an onCompletion, an X is an error. The operator is applied to the top sequence and the result is the sequence below. +Это подходящий момент чтобы представить концепцию мраморных диаграмм. Это популярный метод иллюстрации работы операторов в Rx, так как он достаточно интуитивен и нагляден. Диаграммы присутствуют во многих местах документации по RxJava и есть смысл ориентироваться в них. Формат в основном описывает сам себя: время течет слева направо, фигуры представляют собой данные, прямая(‘|’) - onCompletion, Х - ошибка. Оператор применяется к верхней последовательности и возвращает последовательность снизу. ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/legend.png) ## Filter -`filter` takes a predicate function that makes a boolean decision for each value emitted. If the decision is `false`, the item is omitted from the filtered sequence. +`filter` - принимает функцию предикат которая рассчитывает и возвращает `true` или `false` для каждого испущенного элемента. Если решение ложно(`false`), элемент отбрасывается из фильтруемой последовательности. ```java public final Observable filter(Func1 predicate) @@ -20,7 +20,7 @@ public final Observable filter(Func1 predicate) ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png) -We will use `filter` to create a sequence of numbers and filter out all the even ones, keeping only odd values. +Отфильтруем последовательность чисел и оставим в ней только четные числа. ```java Observable values = Observable.range(0,10); @@ -33,7 +33,7 @@ Subscription oddNumbers = values ); ``` -[Output](/tests/java/itrx/chapter2/reducing/FilterExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/FilterExample.java) ``` 0 2 @@ -43,9 +43,9 @@ Subscription oddNumbers = values Completed ``` -## distinct and distinctUntilChanged +## distinct и distinctUntilChanged -`distinct` filters out any element that has already appeared in the sequence. +`distinct` - отбрасывает элементы, которые уже встречались в последовательности. ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/distinct.png) @@ -67,7 +67,7 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/DistinctExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/DistinctExample.java) ``` 1 2 @@ -75,7 +75,7 @@ Subscription subscription = values Completed ``` -An overload of distinct takes a key selector. For each item, the function generates a key and the key is then used to determine distinctiveness. +Перегрузка `distinct` принимает функцию-селектор ключа. Для каждого элемента функция создает ключ который используется для сравнения уникальности элементов. ```java public final Observable distinct(Func1 keySelector) @@ -83,7 +83,7 @@ public final Observable distinct(Func1 keySelector ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/distinct.key.png) -In this example, we use the first character as a key. +В этом примере используем первую букву в качестве ключа. ```java Observable values = Observable.create(o -> { @@ -103,7 +103,7 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/DistinctExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/DistinctExample.java) ``` First Second @@ -111,11 +111,11 @@ Third Completed ``` -"Fourth" and "Fifth" were filtered out because their first character is 'F' and that has already appeared in "First". +"Fourth" и "Fifth" были отброшены так как начинаются с ‘F’, а этот ключ уже встречался в "First". -An experienced programmer already knows that this operator maintains a set internally with every unique value that passes through the observable and checks every new value against it. While Rx operators neatly hide these things, you should still be aware that an Rx operator can have a significant cost and consider what you are using it on. +Опытные программисты знают, что этот оператор сохраняет каждый уникальный элемент во внутреннем списке, который прошел через Observable, и проверяет наличие новых элементов в этом списке. Rx аккуратно скрывает такие вещи, вы должны быть в курсе, что это может привести к значительным вычислительным затратам. -A variant of `distinct` is `distinctUntilChanged`. The difference is that only consecutive non-distinct values are filtered out. +Разновидность `distinct` - `distinctUntilChanged`. Разница заключается в том, что последовательные неуникальные значения отбрасываются. ```java public final Observable distinctUntilChanged() @@ -142,7 +142,7 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/DistinctExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/DistinctExample.java) ``` 1 2 @@ -151,7 +151,7 @@ Subscription subscription = values Completed ``` -You can you use a key selector with `distinctUntilChanged`, as well. +Вы также можете использовать селектор ключа с `distinctUntilChanged`. ```java Observable values = Observable.create(o -> { @@ -171,7 +171,7 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/DistinctExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/DistinctExample.java) ``` First Second @@ -182,7 +182,7 @@ Completed ## ignoreElements -`ignoreElements` will ignore every value, but lets pass through `onCompleted` and `onError`. +`ignoreElements` - игнорирует каждое значение, но пропускает `onCompleted` и `onError`. ```java Observable values = Observable.range(0, 10); @@ -195,20 +195,20 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/IgnoreExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/IgnoreExample.java) ``` Completed ``` -`ignoreElements()` produces the same result as `filter(v -> false)` +`ignoreElements()` - производит такой же результат, что и `filter(v -> false)` -## skip and take +## skip и take -The next group of methods serve to cut the sequence at a specific point based on the item's index, and either take the first part or the second part. `take` takes the first n elements, while `skip` skips them. Note that neither function considers it an error if there are fewer items in the sequence than the specified index. +Следующая группа элементов служит для обрезания последовательности в определенной точке базируясь на индексе элемента, и возвращает либо первую либо вторую часть. `take` берет первые n элементов, в то время как `skip` пропускает их. Обратите внимание, что ни один из операторов не считает ошибкой если количество элементов в последовательности меньше указанного индекса. ```java -Observable take(int num) +Observable take(int num) ``` ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/take.png) @@ -225,16 +225,16 @@ Subscription first2 = values ); ``` -[Output](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) ``` 0 1 Completed ``` -Users of Java 8 streams should know the `take` operator as `limit`. The `limit` operator exists in Rx too, for symmetry purposes. It is an alias of `take`, but it lacks the richer overloads that we will soon see. +Пользователи Stream API из Java 8 должны знать оператор `take` как `limit`. Оператор `limit` также присутствует в RxJava 1.X для тех же целей. Это синоним для `take`, но ему не достаёт перегрузок которые мы скоро увидим. В RxJava 2+ оператор `limit` был исключен. -`take` completes as soon as the n-th item is available. If an error occurs, the error will be forwarded, but not if it occurs after the cutting point. `take` doesn't care what happens in the observable after the n-th item. +`take` - завершится как только получит n-й элемент. Если произойдет ошибка, она будет проброшена в том случае если она произошла до n-го элемента. `take` - не заботится о том что произошло с Observable после n-го элемента, так как это уже другая, "родительская" последовательность. ```java Observable values = Observable.create(o -> { @@ -250,16 +250,16 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) ``` 1 Completed ``` -`skip` returns the other half of a `take`. +`skip` возвращает оставшуюся часть от `take`. ```java -Observable skip(int num) +Observable skip(int num) ``` ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/skip.png) @@ -275,7 +275,7 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) ``` 2 3 @@ -283,11 +283,11 @@ Subscription subscription = values Completed ``` -There are overloads where the cutoff is a moment in time rather than place in the sequence. +Есть перегруженные версии операторов где последовательность обрезается в определенный момент времени а не на конкретном элементе. ```java -Observable take(long time, java.util.concurrent.TimeUnit unit) -Observable skip(long time, java.util.concurrent.TimeUnit unit) +Observable take(long time, java.util.concurrent.TimeUnit unit) +Observable skip(long time, java.util.concurrent.TimeUnit unit) ``` ```java @@ -301,7 +301,7 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) ``` 0 1 @@ -310,10 +310,10 @@ Completed ## skipWhile and takeWhile -`take` and `skip` work with predefined indices. If you want to "discover" the cutoff point as the values come, `takeWhile` and `skipWhile` will use a predicate instead. `takeWhile` takes items while a predicate function returns `true` +`take` и `skip` работают с предопределенными индексами. Однако, если вам нужно найти точку отсечения основываясь на входных данных используйте условные `takeWhile` и `skipWhile`. `takeWhile` пропускает значение пока функция предикат возвращает `true`. ```java -Observable takeWhile(Func1 predicate) +Observable takeWhile(Func1 predicate) ``` ```java @@ -327,14 +327,14 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) ``` 0 1 Completed ``` -As you would expect, `skipWhile` returns the other half of the sequence +Как и ожидалось, `skipWhile` вернет оставшуюся часть последовательности. ```java Observable values = Observable.interval(100, TimeUnit.MILLISECONDS); @@ -347,7 +347,7 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) ``` 2 3 @@ -355,9 +355,9 @@ Subscription subscription = values ... ``` -## skipLast and takeLast +## skipLast и takeLast -`skipLast` and `takeLast` work just like `take` and `skip`, with the difference that the point of reference is from the end. +`skipLast` и `takeLast` работают также как `take` и `skip`, с тем отличием, что точка отсечения отсчитывается с конца. ```java Observable values = Observable.range(0,5); @@ -370,22 +370,21 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) ``` 0 1 2 Completed ``` +К настоящему времени вы должны догадываться как соотносяться `takeLast` и `skipLast`. Также присутствуют перегрузки с индексами и со временем. -By now you should be able to guess how `takeLast` is related to `skipLast`. There are overloads for both indices and time. +## takeUntil и skipUntil -## takeUntil and skipUntil +Есть еще два метода - `takeUntil` и `skipUntil`. `takeUntil` работает точно так же как `takeWhile` за исключением того, что он принимает элементы пока предикат возвращает `false`. Так же ведет себя и `skipUntil`. -There are also two methods named `takeUntil` and `skipUntil`. `takeUntil` works exactly like `takeWhile` except that it takes items while the predictate is false. The same is true of `skipUntil`. - -Along with that, `takeUntil` and `skipUntil` each have a very interesting overload. The cutoff point is defined as the moment when _another_ observable emits an item. +Наряду с этим, `takeUntil` и` skipUntil` имеют очень интересную перегрузку. Точка отсечки определяется в момент, когда другой _Observable_ выдает новый элемент последовательности. ```java public final Observable takeUntil(Observable other) @@ -405,16 +404,15 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) ``` 0 1 Completed ``` +Как вы помните, `timer` ожидает 250мс и испускает одно событие. `takeUntil` реагирует на этот сигнал и останавливает последовательность. Обратите внимание что сигнал может быть любого типа, так как его значение не используется. -As you may remember, `timer` here will wait 250ms and emit one event. This signals `takeUntil` to stop the sequence. Note that the signal can be of any type, since the actual value is not used. - -Once again `skipUntil` works by the same rules and returns the other half of the observable. Values are ignored until the signal comes to start letting values pass through. +Еще раз, `skipUntil` работает по тем же правилам и возвращает вторую половину последовательности. Элементы игнорируются пока не придет сигнал о начале трансляции элементов насквозь. ```java Observable values = Observable.interval(100,TimeUnit.MILLISECONDS); @@ -428,7 +426,7 @@ Subscription subscription = values () -> System.out.println("Completed") ); ``` -[Output](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) +[Вывод](/tests/java/itrx/chapter2/reducing/TakeSkipExample.java) ``` 2 3 @@ -437,8 +435,8 @@ Subscription subscription = values ``` -#### Continue reading +#### Продолжить чтение -| Previous | Next | +| Назад | Вперед | | --- | --- | -| [Creating a sequence](/Part 2 - Sequence Basics/1. Creating a sequence.md) | [Inspection](/Part 2 - Sequence Basics/3. Inspection.md) | +| [Создание последовательности](/Part 2 - Sequence Basics/1. Creating a sequence.md) | [Исследование последовательности](/Part 2 - Sequence Basics/3. Inspection.md) | diff --git a/Part 2 - Sequence Basics/3. Inspection.md b/Part 2 - Sequence Basics/3. Inspection.md index 893edf6..c0ae5ca 100644 --- a/Part 2 - Sequence Basics/3. Inspection.md +++ b/Part 2 - Sequence Basics/3. Inspection.md @@ -1,13 +1,13 @@ -# Inspection +# Исследование последовательности -In the previous chapter we just saw ways to filter out data that we don't care about. Sometimes what we want is information about the sequence rather than the values themselves. We will now introduce some methods that allow us to reason about a sequence. +В предыдущей главе мы изучали способы фильтрации данных которые важны для нас. Иногда информация о последовательности является более важной нежели ее значения. Сейчас мы рассмотрим некоторые методы, которые позволят нам рассуждать о содержимом последовательности. ## all -The `all` method establishes that every value emitted by an observable meets a criterion. Here's the signature and an example: +`all` - метод который проверяет, что каждое значение произведенное последовательностью отвечает заданному критерию. Вот сигнатура метода и пример: ```java -public final Observable all(Func1 predicate) +public final Observable all(Funk predicate) ``` ```java @@ -29,13 +29,14 @@ Subscription evenNumbers = values ); ``` -[Output](/tests/java/itrx/chapter2/inspection/AllExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/AllExample.java) ``` true Completed ``` +Любопытный факт, то что этот метод возвращает последовательность с одним значением, а не логическое значение напрямую. Это все потому что неизвестно сколько времени потребуется чтоб определить ложный или истинный результат. Как только решение будет получено последовательность завершится, даже если исходная последовательность еще не завершилась. Как только предикат вернет `false` для некоторого значения, `false` - будет испущено. `true` не может быть испущено до тех пор пока исходная последовательность завершится и _все_ элементы будут проверены. Это удобный способ сделать операцию асинхронной. -An interesting fact about this method is that it returns an observable with a single value, rather than the boolean value directly. This is because it is unknown how long it will take to establish whether the result should be true or false. Even though it completes as soon as it can know, that may take as long the source sequence itself. As soon as an item fails the predicate, `false` will be emitted. A value of `true` on the other hand cannot be emitted until the source sequence has completed and _all_ of the items are checked. Returning the decision inside an observable is a convenient way of making the operation non-blocking. We can see `all` failing as soon as possible in the next example: +В следующем примере оператор `all` возвращает последовательность, которая выдает `false` сразу же после того как предикат возвращает `false` для элемента: ```java Observable values = Observable.interval(150, TimeUnit.MILLISECONDS).take(5); @@ -55,7 +56,7 @@ Subscription subscription2 = values ); ``` -[Output](/tests/java/itrx/chapter2/inspection/AllExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/AllExample.java) ``` 0 1 @@ -67,7 +68,7 @@ All: Completed Completed ``` -If the source observable emits an error, then `all` becomes irrelevant and the error passes through, terminating the sequence. +Если исходная последовательность возвращает ошибку, тогда `all` также возвращает ошибку и последовательность завершается. ```java Observable values = Observable.create(o -> { @@ -85,12 +86,11 @@ Subscription subscription = values ); ``` -[Output](/tests/java/itrx/chapter2/inspection/AllExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/AllExample.java) ``` Error: java.lang.Exception ``` - -If, however, the predicate fails, then `false` is emitted and the sequence terminates. Even if the source observable fails after that, the event is ignored, as required by the Rx contract (no events after a termination event). +В случае если ,предикат не удовлетворяет заданному критерию, тогда испускается `false` и последовательность завершается. Если исходная последовательность после этого завершиться с ошибкой, она будет проигнорирована, так как это требуют принципы Rx (никаких событий после события завершения). ```java Observable values = Observable.create(o -> { @@ -108,7 +108,7 @@ Subscription subscription = values ); ``` -[Output](/tests/java/itrx/chapter2/inspection/AllExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/AllExample.java) ``` false Completed @@ -116,7 +116,7 @@ Completed ## exists -The exists method returns an observable that will emit `true` if any of the values emitted by the observable make the predicate true. +`exists` - возвращает `Observable`, который вернет `true` если хотя бы одно из значений наблюдаемой(исходной) последовательности будет соответствовать предикату. ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/exists.png) @@ -132,13 +132,14 @@ Subscription subscription = values ); ``` -[Output](/tests/java/itrx/chapter2/inspection/ExistsExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/ExistsExample.java) ``` false Completed ``` -Here our range didn't go high enough for the `i > 2` condition to succeed. If we extend our range in the same example with +Здесь наш диапазон недостаточно длинный чтоб выполнить условие `i > 2`. Если мы расширим диапазон с тем же условием: + ```java Observable values = Observable.range(0, 4); ``` @@ -150,7 +151,7 @@ Completed ## isEmpty -This operator's result is a boolean value, indicating if an observable emitted values before completing or not. +Оператор возвращает логическое значение указывающее выдавала ли исходная последовательность элементы до завершения или нет. ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/isEmpty.png) @@ -166,17 +167,16 @@ Subscription subscription = values ); ``` -[Output](/tests/java/itrx/chapter2/inspection/IsEmptyExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/IsEmptyExample.java) ``` false Completed ``` - -Falsehood is established as soon as the first value is emitted. `true` will be returned once the source observable has terminated. +`false` появится как только исходная последовательность выдаст значение. `true` будет выдано, если исходная последовательность завершится не выдав значений. Например `Observable.empty()`. ## contains -The method `contains` establishes if a particular element is emitted by an observable. `contains` will use the `Object.equals` method to establish the equality. Just like previous operators, it emits its decision as soon as it can be established and immediately completes. +Оператор `contains` определяет был ли испущен определенный элемент. `contains` использует `Object.equals` метод для определения эквивалентности. Так же как и предыдущие операторы, он испускает решение как только оно посчитано и сразу же завершается. ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/contains.png) @@ -192,17 +192,17 @@ Subscription subscription = values ); ``` -[Output](/tests/java/itrx/chapter2/inspection/ContainsExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/ContainsExample.java) ``` true Completed ``` -If we had used `contains(4)` where we used `contains(4L)`, nothing would be printed. That's because `4` and `4L` are not equal in Java. Our code would wait for the observable to complete before returning false, but the observable we used is infinite. +Если мы напишем `contains(4)` вместо `contains(4L)`, ничего не будет напечатано. Это потому что `4` и `4L` не эквивалентны в Java. Наш код будет ждать окончания последовательности до того как испустить `false`, но этого никогда не случится, так как наша последовательность бесконечна. ## defaultIfEmpty -If an empty sequence would cause you problems, rather than checking with `isEmpty` and handling the case, you can force an observable to emit a value on completion if it didn't emit anything before completing. +Если пустая последовательность оказалась пустой, вместо проверки на `isEmpty` и обработки вручную, вы можете заставить последовательность выдать значение "по умолчанию" перед завершением. ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/defaultIfEmpty.png) @@ -218,13 +218,13 @@ Subscription subscription = values ); ``` -[Output](/tests/java/itrx/chapter2/inspection/DefaultIfEmptyExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/DefaultIfEmptyExample.java) ``` 2 Completed ``` -The default value is emitted only if no other values appeared and only on successful completion. If the source is not empty, the result is just the source observable. In the case of the error, the default value will _not_ be emitted before the error. +Если источник не будет пустым, результатом будет последовательность источника. В случае ошибки значение по умолчанию _не_ будет испущено перед событием ошибки. ```java Observable values = Observable.error(new Exception()); @@ -238,14 +238,14 @@ Subscription subscription = values ); ``` -Output +[Вывод] ``` Error: java.lang.Exception ``` ## elementAt -You can select exactly one element out of an observable using the `elementAt` method +Вы можете выбрать один элемент из последовательности используя метод `elementAt` ![](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/elementAt.png) @@ -261,13 +261,13 @@ Subscription subscription = values ); ``` -[Output](/tests/java/itrx/chapter2/inspection/ElementAtExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/ElementAtExample.java) ``` 102 Completed ``` -If the sequence doesn't have enough items, an `java.lang.IndexOutOfBoundsException` will be emitted. To avoid that specific case, we can provide a default value that will be emitted instead of an `IndexOutOfBoundsException`. +Если последовательность недостаточной длины, будет выброшено исключение `java.lang.IndexOutOfBoundsException`. Чтоб предотвратить этот специфический случай, мы можем определить значение по умолчанию чтобы оно возвращалось взамен `IndexOutOfBoundsException`. ```java Observable values = Observable.range(100, 10); @@ -281,7 +281,7 @@ Subscription subscription = values ); ``` -[Output](/tests/java/itrx/chapter2/inspection/ElementAtExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/ElementAtExample.java) ``` 0 Completed @@ -289,7 +289,7 @@ Completed ## sequenceEqual -The last operator for this chapter establishes that two sequences are equal by comparing the values at the same index. Both the size of the sequences and the values must be equal. The function will either use `Object.equals` or the function that you supply to compare values. +Последний оператор представлений в этой главе, определяет являются ли две последовательности эквивалентны, сравнивая элементы с одинаковыми индексами. И размеры и значения последовательностей должны быть одинаковыми. Для сравнения используется `Object.equals` или ваша собственная функция для сравнения значений. ```java Observable strings = Observable.just("1", "2", "3"); @@ -304,15 +304,15 @@ Observable.sequenceEqual(strings, ints, (s,i) -> s.equals(i.toString())) ); ``` -[Output](/tests/java/itrx/chapter2/inspection/SequenceEqualExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/SequenceEqualExample.java) ``` true Completed ``` -If we swap the operator for the one that is commented out, i.e, the one using the standard `Object.equals`, the result would be `false`. +Если мы будем использовать закомментированный оператор, он будет использовать `Object.equals` для сравнения, и результат окажется `false`. -Failing is not part of the comparison. As soon as either sequence fails, the resulting observable forwards the error. +Исключительная ситуация не является частью сравнения. Как только одна из последовательностей выйдет из строя, результирующая последовательность выдаст ошибку. ```java Observable values = Observable.create(o -> { @@ -329,13 +329,13 @@ Observable.sequenceEqual(values, values) ); ``` -[Output](/tests/java/itrx/chapter2/inspection/SequenceEqualExample.java) +[Вывод](/tests/java/itrx/chapter2/inspection/SequenceEqualExample.java) ``` Error: java.lang.Exception ``` -#### Continue reading +#### Продолжить чтение -| Previous | Next | +| Назад | Вперед | | --- | --- | -| [Reducing a sequence](/Part 2 - Sequence Basics/2. Reducing a sequence.md) | [Aggregation](/Part 2 - Sequence Basics/4. Aggregation.md) | +| [Фильтрация последовательности](/Part 2 - Sequence Basics/2. Reducing a sequence.md) | [Агрегация](/Part 2 - Sequence Basics/4. Aggregation.md) | diff --git a/README.md b/README.md index f250803..c63b99e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ### Структура -Материал этих статей расчитан на прочтение от начала до конца. Его обьем больше, чем среднего туториала, но меньше чем реальной книги. Мы начнем с самых основ и от раздела к разделу будем переходить к всё более продвинутым сценариям и концепциям. Каждый раздел задумывался самодостаточным и лаконичным для того, чтобы к нему можно было вернуться в будущем. +Материал этих статей рассчитан на прочтение от начала до конца. Его объем больше среднего туториала, но меньше реальной книги. Мы начнем с самых основ и, от раздела к разделу, будем переходить к всё более продвинутым сценариям и концепциям. Каждый раздел задумывался самодостаточным и лаконичным для того, чтобы к нему можно было вернуться в будущем. Примеры к этим материалам доступны в двух видах: @@ -24,5 +24,9 @@ ### В процессе перевода -Многие части все еще не переведены. Помощь в виде пул-реквестов с переводами и исправлениями очень привествуется. +Многие части все еще не переведены. Помощь в виде пул-реквестов с переводами и исправлениями очень приветствуется. +### Участники +* [FARsh](https://github.com/FARsh) +* [KlGleb](https://github.com/KlGleb) +* [AnatolyBurtsev](https://github.com/anatolyburtsev)