Главная страница
Навигация по странице:

  • Абстрактные методы it.next()Возвращает следующий элемент в итераторе и продвига­ется за него it.hasNextВозвращает true, если может вернуть еще элементВариации

  • Дублирование it.duplicateПара итераторов, каждый из которых независимо от другого возвращает все элементы itДобавления

  • Индексированный поиск с извлечением элемента

  • Таблица 24.14

  • Специализированные свертки

  • Обновление it.patch(i, jt, r)Итератор, получаемый из it путем замены r элементов, начиная с позиции i, итератором вставки jt 570

  • Таблица 24.15.

  • Scala. Профессиональное программирование 2022. Одерски Мартин, Спун Лекс, Веннерс Билл, Соммерс ФрэнкО41 Scala. Профессиональное программирование. 5е изд спб. Питер, 2022. 608 с. ил. Серия Библиотека программиста


    Скачать 6.24 Mb.
    НазваниеОдерски Мартин, Спун Лекс, Веннерс Билл, Соммерс ФрэнкО41 Scala. Профессиональное программирование. 5е изд спб. Питер, 2022. 608 с. ил. Серия Библиотека программиста
    Дата27.04.2023
    Размер6.24 Mb.
    Формат файлаpdf
    Имя файлаScala. Профессиональное программирование 2022.pdf
    ТипДокументы
    #1094967
    страница60 из 64
    1   ...   56   57   58   59   60   61   62   63   64
    565
    Как видите, после вызова map итератор it не перешел в конец, а вот итератор, полученный в результате вызова it.map
    , можно перебрать до конца.
    Еще один пример — метод dropWhile
    , который может использоваться для поиска первого элемента итератора, имеющего определенное свойство. На­
    пример, для поиска в ранее показанном итераторе первого слова, в котором как минимум два символа, можно задействовать следующий код:
    val it = Iterator("a", "number", "of", "words")
    val dit = it.dropWhile(_.length < 2)
    dit.next() // number it.next() // of
    Еще раз обратите внимание на то, что it был изменен вызовом dropWhile
    : теперь it указывает на второе слово "number"
    в списке. Фактически it и ре­
    зультат res
    , полученный при выполнении dropWhile
    , вернут одинаковую последовательность элементов.
    Есть только одна стандартная операция, duplicate
    , позволяющая повторно использовать один и тот же итератор:
    val (it1, it2) = it.duplicate
    Вызов метода duplicate возвращает два итератора, каждый из которых воз­
    вращает точно такие же элементы, что и итератор it
    . Оба итератора работают независимо друг от друга, продвижение одного из них совершенно не влияет на состояние другого. В отличие от этого исходный итератор it продвигается при вызове duplicate в самый конец и становится непригодным для даль­
    нейшего использования.
    В целом итераторы ведут себя как коллекции, если вы никогда не обра-
    щаетесь к итератору еще раз после вызова метода на нем. Библиотеки коллекций Scala делают это явным с помощью абстракции под названием
    IterableOnce
    , которая является обобщающим супертрейтом для
    Iterable и
    Iterator
    . Судя по названию, объекты типа
    IterableOnce допускают обход своих элементов хотя бы однократно, но состояние таких объектов после обхода не определено. Если объект типа
    IterableOnce фактически относится к типу
    Iterator
    , то после обхода будет указывать на конец коллекции, если же относится к типу
    Iterable
    , то не изменит своего состояния. Чаще всего
    IterableOnce используется как тип аргумента для методов, который могут получать в качестве аргумента
    Iterator или
    Iterable
    . Примером может по­
    служить метод добавления
    ++
    в трейте
    Iterable
    . Он получает параметр типа
    IterableOnce
    , позволяя добавлять элементы, получаемые как из коллекции типа
    Iterator
    , так и из
    Iterable

    566 Глава 24 • Углубленное изучение коллекций
    Все операции над итераторами сведены в табл. 24.14.
    Таблица 24.14. Операции в трейте Iterator
    Что
    Что делает
    Абстрактные методы
    it.next()
    Возвращает следующий элемент в итераторе и продвига­
    ется за него it.hasNext
    Возвращает true
    , если может вернуть еще элемент
    Вариации
    it.buffered
    Буферизованный итератор, возвращающий все элемен­
    ты it it.grouped(size)
    Итератор, выдающий элементы, возвращаемые it, блока­
    ми фиксированного размера it.sliding(size)
    Итератор, выдающий элементы, возвращаемые it
    , в виде скользящего по коллекции окна фиксированного раз­
    мера
    Копирование
    it.copyToArray(arr, s, l)
    Копирует не более одного элемента, возвращенного it
    , в массив arr
    , начиная с индекса s
    . Последние два аргу­
    мента являются необязательными
    Дублирование
    it.duplicate
    Пара итераторов, каждый из которых независимо от другого возвращает все элементы it
    Добавления
    it ++ jt
    Итератор, выдающий все элементы, возвращаемые итератором it
    , а затем все элементы, возвращаемые итератором jt it.padTo(len,x)
    Итератор, выдающий все элементы it
    , а затем копии x
    до тех пор, пока не будет полностью достигнута дли­
    на len
    Отображения
    it.map(f)
    Итератор, получаемый в результате применения функ­
    ции к каждому элементу, возвращаемому it it.flatMap(f)
    Итератор, получаемый в результате применения воз­
    вращающей итератор функции f
    к каждому элементу it и добавления результатов

    24 .14 . Итераторы 567
    Что
    Что делает
    it.collect(f)
    Итератор, получаемый в результате использования ча­
    стично примененной функции f
    к каждому элементу it
    , для которого она определена, и сбора результатов
    Преобразования
    it.toArray
    Собирает возвращаемые it элементы в массив it.toList
    Собирает возвращаемые it элементы в список it.toIterable
    Собирает возвращаемые it элементы в коллекцию
    Iterable it.toSeq
    Собирает возвращаемые it элементы в последователь­
    ность it.toIndexedSeq
    Собирает возвращаемые it элементы в индексирован­
    ную последовательность it.toSet
    Собирает возвращаемые it элементы в множество it.toMap
    Собирает возвращаемые it пары «ключ — значение» в отображение it to SortedSet
    Обобщенная операция преобразования, принимающая в качестве параметра фабрику коллекций
    Информация о размере
    it.isEmpty
    Проверяет, пуст ли итератор (противоположность hasNext
    )
    it.nonEmpty
    Проверяет, содержит ли итератор элементы (псевдоним метода hasNext
    )
    it.size
    Количество элементов, возвращенных it
    (после этой операции it окажется в самом конце!)
    it.length
    То же самое, что и it.size it.knownSize
    Количество элементов, если его можно узнать без изме­
    нения состояния итератора; в противном случае –1
    Индексированный поиск с извлечением элемента
    it.find(p)
    Option
    ­значение, содержащее первый возвращаемый it элемент, удовлетворяющий условию p
    , или
    None при отсутствии таких элементов (итератор продвигается за найденный элемент или, если не найден ни один эле­
    мент, оказывается в конечной позиции)
    it.indexOf(x)
    Индекс первого возвращенного it элемента, равного x
    (итератор продвигается за найденный элемент)

    568 Глава 24 • Углубленное изучение коллекций
    Что
    Что делает
    it.indexWhere(p)
    Индекс первого возвращенного it элемента, удовлетво­
    ряющего условию p
    (итератор продвигается за найден­
    ный элемент)
    Подытераторы
    it.take(n)
    Итератор, выдающий первые n
    элементов итератора it
    (
    it продвинется за позицию n
    ­го элемента или же оказывается в конечной позиции, если в it содержится меньше n
    элементов)
    it.drop(n)
    Итератор, начинающий выборку с элемента it с позиции
    (
    n
    + 1) (
    it продвинется до этой же позиции)
    it.slice(m, n)
    Итератор, выдающий блок элементов, возвращенный из it
    , начинающийся с m
    ­го элемента и заканчивающий­
    ся перед n
    ­м элементом it.takeWhile(p)
    Итератор, выдающий элементы из it
    , пока условие p
    вычисляется в true it.dropWhile(p)
    Итератор, пропускающий элементы из it
    , пока усло­
    вие p
    вычисляется в true
    , и выдающий остаток it.filter(p)
    Итератор, выдающий все элементы из it
    , удовлетворяю­
    щие условию p
    it.withFilter(p)
    То же самое, что и it filter p
    . Эта операция необходима для использования итераторов в выражениях for it.filterNot(p)
    Итератор, выдающий все элементы из it
    , не удовлетво­
    ряющие условию p
    it.distinct
    Итератор, выдающий все элементы из it
    , не включая дубликаты
    Деление
    it.partition(p)
    Разбивает it на два итератора, один из которых возвра­
    щает из it все элементы, удовлетворяющие условию p
    , а другой — все элементы, не удовлетворяющие этому условию
    Состояния элементов
    it.forall(p)
    Булево значение, показывающее, соблюдается ли усло­
    вие p
    для всех элементов, возвращаемых it it.exists(p)
    Булево значение, показывающее, соблюдается ли усло­
    вие p
    для какого­либо из элементов, возвращаемых it
    Таблица 24.14 (продолжение)

    24 .14 . Итераторы 569
    Что
    Что делает
    it.count(p)
    Количество элементов в it
    , удовлетворяющих условию p
    Свертки
    it.foldLeft(z)(op)
    Применяет бинарную операцию op к соседним эле­
    ментам, возвращаемым it
    , проходя коллекцию слева направо и начиная с z
    it.foldRight(z)(op)
    Применяет бинарную операцию op к соседним эле­
    ментам, возвращаемым it
    , проходя коллекцию справа налево и начиная с z
    it.reduceLeft(op)
    Применяет бинарную операцию op к соседним элемен­
    там, возвращаемым непустым итератором it
    , проходя коллекцию слева направо it.reduceRight(op)
    Применяет бинарную операцию op к соседним элемен­
    тами, возвращаемым непустым итератором it
    , проходя коллекцию справа налево
    Специализированные свертки
    it.sum
    Сумма значений числовых элементов, выдаваемых итератором it it.product
    Произведение значений числовых элементов, выдавае­
    мых итератором it it.min
    Минимальное значение упорядочиваемых элементов, выдаваемых итератором it it.max
    Максимальное значение упорядочиваемых элементов, выдаваемых итератором it
    Слияния
    it zip jt
    Итератор пар соответствующих элементов, выдаваемых итераторами it и jt it.zipAll(jt, x, y)
    Итератор пар соответствующих элементов, выдаваемых итераторами it и jt
    , причем тот итератор, что короче, расширяется, чтобы соответствовать более длинному итератору путем добавления элементов x
    или y
    it.zipWithIndex
    Итератор пар, состоящих из элементов, возвращае­
    мых it
    , и их индексов
    Обновление
    it.patch(i, jt, r)
    Итератор, получаемый из it путем замены r
    элементов, начиная с позиции i
    , итератором вставки jt

    570 Глава 24 • Углубленное изучение коллекций
    Что
    Что делает
    Сравнение
    it.sameElements(jt)
    Проверяет, не возвращают ли итераторы it и
    jt одни и те же элементы в одном и том же порядке. Обрати­
    те внимание: после этой операции следует отбросить как it
    , так и jt
    Строки
    it.addString(b, start, sep, end)
    Добавляет строку к
    StringBuilder b
    , которая показывает все элементы, возвращаемые it
    , между разделителями sep и заключена в строковые значения start и end
    . Аргу­
    менты start
    , sep и end являются необязательными it.mkString(start, sep, end)
    Преобразует итератор в строку, показывающую все элементы, возвращаемые it
    , между разделителями sep
    , и заключенную в строковые значения start и end
    . Аргу­
    менты start
    , sep и end являются необязательными
    Буферизованные итераторы
    Порой бывает необходим итератор, способный заглянуть вперед, позволяя проинспектировать следующий возвращаемый элемент, не продвигаясь за него. Рассмотрим, к примеру, задачу пропуска начальных пустых строк ите­
    ратора, который возвращает последовательность строк. Возможно, возникнет соблазн создать нечто похожее на метод, показанный ниже:
    // Этот код работать не будет def skipEmptyWordsNOT(it: Iterator[String]) =
    while it.next().isEmpty do {}
    Но, присмотревшись, можно понять, что этот код неработоспособен: разуме­
    ется, он будет пропускать начальные пустые строки, но также продвинет it за первую непустую строку!
    Решить эту задачу можно с помощью буферизованного итератора, эк­
    земпляра трейта
    BufferedIterator
    , который является подтрейтом трейта
    Iterator и предоставляет еще один метод по имени head
    . Вызов head в отношении буферизованного итератора приведет к возвращению его первого элемента, но без продвижения итератора. При использовании бу­
    феризованного итератора код для пропуска пустых слов может выглядеть следующим образом:
    Таблица 24.14 (окончание)

    24 .15 . Создание коллекций с нуля 571
    def skipEmptyWords(it: BufferedIterator[String]) =
    while it.head.isEmpty do it.next()
    Каждый итератор может быть преобразован в буферизованный итератор путем вызова своего метода buffered
    . Пример его использования выглядит так:
    val it = Iterator(1, 2, 3, 4)
    val bit = it.buffered bit.head // 1
    bit.next() // 1
    bit.next() // 2
    Следует заметить, что вызов head в отношении буферизованного итератора bit не приводит к изменению позиции итератора. Поэтому последующий вызов, bit.next()
    , возвращает то же самое значение, что и bit.head
    24 .15 . Создание коллекций с нуля
    Вам уже попадался синтаксис наподобие
    List(1,
    2,
    3)
    , который создает список из трех целых чисел, и
    Map('A'
    –>
    1,
    'C'
    –>
    2)
    , который создает ото­
    бражение с двумя привязками. Фактически это универсальная возможность коллекций Scala. Можно взять любое имя коллекции и указать после него в круглых скобках список элементов. В результате получится новая коллек­
    ция с заданными элементами. Ниже представлены еще примеры:
    Iterable() // пустая коллекция
    List() // пустой список
    List(1.0, 2.0) // список с элементами 1.0, 2.0
    Vector(1.0, 2.0) // вектор с элементами 1.0, 2.0
    Iterator(1, 2, 3) // итератор, возвращающий три целых числа
    Set(dog, cat, bird) // множество из трех животных
    HashSet(dog, cat, bird) // хеш-множество из тех же животных
    Map('a' –> 7, 'b' –> 0) // отображение символов на целые числа
    «Скрытно» каждая из показанных ранее строк является вызовом метода apply определенного объекта. Например, третья из этих строк раскрывается в следующий код:
    List.apply(1.0, 2.0)
    Здесь показан вызов метода apply
    , принадлежащего объекту­компаньону класса
    List
    . Этот метод получает произвольное число аргументов и создает из них список. Каждый класс коллекций в библиотеке Scala располагает

    572 Глава 24 • Углубленное изучение коллекций объектом­компаньоном с таким же методом apply
    . И неважно, представлена конкретная реализация классом коллекции, как в случае с
    List
    ,
    LazyList или
    Vector
    , или же трейтом, как в случае с
    Seq
    ,
    Set или
    Iterable
    . В последнем случае вызов apply приведет к созданию некой исходной реализации трейта.
    Рассмотрим ряд примеров:
    scala> List(1, 2, 3)
    val res17: List[Int] = List(1, 2, 3)
    scala> Iterable(1, 2, 3)
    val res18: Iterable[Int] = List(1, 2, 3)
    scala> mutable.Iterable(1, 2, 3)
    val res19: scala.collection.mutable.Iterable[Int] =
    ArrayBuffer(1, 2, 3)
    Помимо apply
    , в каждом объекте­компаньоне определен и элемент empty
    , возвращающий пустую коллекцию. Поэтому вместо
    List()
    можно вос­
    пользоваться кодом
    List.empty
    , вместо
    Map()
    задействовать код
    Map.empty и т. д.
    Кроме того, потомки трейтов
    Seq и
    Set в своих объектах­компаньонах пре­
    доставляют другие факторные операции, которые сведены в табл. 24.15.
    Вкратце это:
    z z
    concat
    , которая конкатенирует произвольное количество коллекций;
    z z
    fill и tabulate
    , которые создают одно­ или многоразмерные коллекции заданной размерности, инициализированные каким­либо выражением или функцией составления таблицы;
    z z
    range
    , которая создает коллекции целых чисел с какой­либо постоянной длиной шага;
    z z
    iterate и unfold
    , которые создают последовательность, получающуюся из многократного применения функции к начальному элементу или со­
    стоянию.
    Таблица 24.15. Фабричные методы для трейтов Seq и Set
    Что
    Что делает
    C.empty
    Пустая коллекция
    C(x, y, z)
    Коллекция, состоящая из элементов x
    , y
    и z
    C.concat(xs, ys, zs)
    Коллекция, получаемая конкатенацией элементов коллекций xs
    , ys и zs

    24 .16 . Преобразования между коллекциями Java и Scala 573
    Что
    Что делает
    C.fill(n)(e)
    Коллекция длиной n
    , где каждый элемент вычисля­
    ется выражением e
    C.fill(m, n)(e)
    Коллекция коллекций размерностью m
    × n
    , где каждый элемент вычисляется выражением e
    (суще­
    ствует также в более высоких измерениях)
    C.tabulate(n)(f)
    Коллекция длиной n
    , где элемент по каждому ин­
    дексу i
    вычисляется путем вызова f(i)
    C.tabulate(m, n)(f)
    Коллекция коллекций размерностью m
    × n
    , где эле­
    мент по каждому индексу (
    i,
    j
    ) вычисляется путем вызова f(i,
    j)
    (существует также в более высоких измерениях)
    C.range(start, end)
    Коллекция целых чисел start end

    1
    C.range(start, end, step)
    Коллекция целых чисел, начинающаяся со start и наращиваемая с шагом step до значения end
    , ис­
    ключая само это значение
    C.iterate(x, n)(f)
    Коллекция длиной n
    с элементами x,
    f(x),
    f(f(x)),
    C.unfold(init)(f)
    Коллекция, которая использует функцию f
    для вы­
    числения своего следующего элемента и состояния, начиная с состояния init
    24 .16 . Преобразования между коллекциями
    Java и Scala
    Как и в Scala, в Java есть богатая библиотека коллекций. Обе библиотеки имеют много общего. Например, и в той и в другой есть такие категории, как итераторы, итерируемые коллекции, множества, отображения и по­
    следовательности. Но есть и важные различия. В частности, в библиотеках
    Scala уделяется намного больше внимания неизменяемым коллекциям и предоставляется куда больше операций, выполняющих преобразование коллекции в новую коллекцию.
    Иногда может понадобиться выполнить преобразование из одной среды в другую. Например, нужно обратиться к уже существующей Java­коллекции, как если бы это была Scala­коллекция. Или же следует передать одну из коллекций Scala методу Java, который ожидает получения Java­аналога.
    Сделать это не составит никакого труда, так как Scala предлагает в объекте

    574 Глава 24 • Углубленное изучение коллекций
    CollectionConverters удобные преобразования между всеми основными типами коллекций. В частности, двунаправленные преобразования имеются между следующими типами:
    Iterator
    ⇔ java.util.Iterator
    Iterator
    ⇔ java.util.Enumeration
    Iterable
    ⇔ java.lang.Iterable
    Iterable
    ⇔ java.util.Collection mutable.Buffer
    ⇔ java.util.List mutable.Set
    ⇔ java.util.Set mutable.Map
    ⇔ java.util.Map
    Чтобы включить эти преобразования, нужно просто импортировать их:
    scala> import jdk.CollectionConverters.*
    Это делает возможным преобразования между соответствующими коллек­
    циями Scala и Java с помощью методов расширения asScala и asJava
    :
    scala> import collection.mutable.*
    scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3).asJava val jul: java.util.List[Int] = [1, 2, 3]
    scala> val buf: Seq[Int] = jul.asScala val buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3)
    scala> val m: java.util.Map[String, Int] =
    HashMap("abc" –> 1, "hello" –> 2).asJava m: java.util.Map[String,Int] = {hello=2, abc=1}
    Внутренний механизм этих преобразований работает за счет создания объ­
    екта­обертки, пересылающего все операции базовому объекту коллекции.
    Поэтому коллекции при преобразовании между Java и Scala никогда не копируются. Интересной особенностью является то, что при круговом пре­
    образовании из, скажем, Java­типа в соответствующий Scala­тип и обратно, в тот же Java­тип, будет получен точно такой же объект коллекции, который имелся в самом начале.
    Есть также ряд других востребованных Scala­коллекций, которые могут быть преобразованы в Java­типы, но для которых нет соответствующих преобра­
    зований в обратном направлении. К ним относятся:
    Seq
    ⇒ java.util.List mutable.Seq
    ⇒ java.util.List
    Set
    ⇒ java.util.Set
    Map
    ⇒ java.util.Map

    Резюме
    1   ...   56   57   58   59   60   61   62   63   64


    написать администратору сайта