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

  • Замена: buf.patchInPlace(i,xs,n)Заменяет (максимум) n элементов буфера элемен­тами из xs, начиная с индекса iКопирование

  • Проверки contains, apply и subsetOf.

  • Добавления + (псевдоним: incl) и ++ (псевдоним: concat)

  • Таблица 24.5.

  • Удаления xs.emptyПустое множество того же класса, что и xs 24 .5 . Множества 531 Что Что делает Бинарные операции

  • Таблица 24.6.

  • Таблица 24.7.

  • Таблица 24.7

  • Операции поиска apply, get, getOrElse, contains и isDefinedAt

  • Добавления и обновления + (псевдоним: updated), ++ (псевдоним: concat) updateWith и updatedWith

  • Преобразования filterKeys и mapValues

  • Что делает Поиск

  • Таблица 24.10.

  • Преобразование и клонирование

  • 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
    страница56 из 64
    1   ...   52   53   54   55   56   57   58   59   ...   64

    529
    Таблица 24.4. Операции в трейте Buffer
    Что
    Что делает
    Добавления
    buf += x
    (или buf.append(x)
    )
    Добавляет элемент x
    в конец buf и возвращает в ка­
    честве результата сам buf buf ++= xs
    (или buf.appendAll(xs)
    )
    Добавляет в конец буфера все элементы xs x +=: buf
    (или buf.prepend(x)
    )
    Добавляет элемент x
    в начало буфера xs ++=: buf
    (или buf.prependAll(xs)
    )
    Добавляет в начало буфера все элементы xs buf.insert(i, x)
    Вставляет элемент x
    в то место в буфере, на которое указывает индекс i
    buf.insertAll(i, xs)
    Вставляет все элементы xs в то место в буфере, на которое указывает индекс i
    buf.padToInPlace(n, x)
    Добавляет в буфер элементы x
    , пока общее количе­
    ство его элементов не достигнет n
    Удаления
    buf –= x
    (или buf.subtractOne(x)
    )
    Удаляет из буфера элемент x
    buf ––= x
    (или buf.subtractAll(xs)
    )
    Удаляет из буфера все элементы xs buf.remove(i)
    Удаляет из буфера элемент с индексом i
    buf.remove(i, n)
    Удаляет из буфера n
    элементов, начиная с элемента с индексом i
    buf.trimStart(n)
    Удаляет из буфера первые n
    элементов buf.trimEnd(n)
    Удаляет из буфера последние n
    элементов buf.clear()
    Удаляет из буфера все элементы
    Замена:
    buf.patchInPlace(i,
    xs,
    n)
    Заменяет (максимум) n
    элементов буфера элемен­
    тами из xs
    , начиная с индекса i
    Копирование
    buf.clone()
    Новый буфер с теми же элементами, что и в buf

    530 Глава 24 • Углубленное изучение коллекций
    24 .5 . Множества
    Коллекции
    Set
    — это итерируемые
    Iterable
    ­коллекции, которые не содер­
    жат повторяющихся элементов. Общие операции над множествами сведены в табл. 24.5, в табл. 24.6 показаны операции для неизменяемых множеств, а в табл. 24.7 — операции для изменяемых множеств. Операции разбиты на следующие категории.
    z z
    Проверки contains, apply и subsetOf. Метод contains показывает, со­
    держит ли множество заданный элемент. Метод apply для множества является аналогом contains
    , поэтому set(elem)
    — то же самое, что и set contains elem
    . Следовательно, множества могут также использоваться в качестве тестовых функций, возвращающих true для содержащихся в них элементов, например:
    val fruit = Set("apple", "orange", "peach", "banana")
    fruit("peach") // true fruit("potato") // false z
    z
    Добавления + (псевдоним: incl) и ++ (псевдоним: concat) добавляют в множество один и более элементов, возвращая в качестве результата новое множество.
    z z
    Удаления - (псевдоним: excl) и -- (псевдоним: removedAll) удаляют из множества один и более элементов, возвращая новое множество.
    z z
    Операции над множествами для объединения, пересечения и разности множеств. Существуют в двух формах: текстовом и символьном. К тек­
    стовым относятся версии intersect
    , union и diff
    , а к символьным —
    &
    ,
    |
    и
    &


    . Оператор
    ++
    , наследуемый
    Set из
    Iterable
    , может рассматриваться в качестве еще одного псевдонима union или
    |
    , за исключением того, что
    ++
    получает
    IterableOnce
    ­аргумент, а union и
    |
    получают множества.
    Таблица 24.5. Операции в трейте Set
    Что
    Что делает
    Проверки
    xs.contains(x)
    Проверяет, является ли x
    элементом xs xs(x)
    Делает то же самое, что и xs contains x
    xs.subsetOf(ys)
    Проверяет, является ли xs подмножеством ys
    Удаления
    xs.empty
    Пустое множество того же класса, что и xs

    24 .5 . Множества 531
    Что
    Что делает
    Бинарные операции
    xs & ys
    (или xs.intersect(ys)
    )
    Пересечение множеств xs и ys xs | ys
    (или xs.union(ys)
    )
    Объединение множеств xs и ys xs & ys
    (или xs.diff(ys)
    )
    Разность множеств xs и ys
    Неизменяемые множества предлагают методы добавления и удаления эле­
    ментов путем возвращения новых множеств, которые сведены в табл. 24.6.
    Таблица 24.6. Операции в трейте immutable .Set
    Что
    Что делает
    Добавления
    xs + x
    (или xs.incl(x)
    )
    Множество, содержащее все элементы xs и эле­
    мент x
    xs ++ ys
    (или xs.concat(ys)
    )
    Множество, содержащее все элементы xs и все элементы ys
    Удаления
    xs – x
    (или xs.excl(x)
    )
    Множество, содержащее все элементы xs
    , кроме x
    xs –– ys
    (или xs.removedAll(ys)
    )
    Множество, содержащее все элементы xs
    , кроме элементов множества ys
    У изменяемых множеств есть методы, которые добавляют, удаляют и обнов­
    ляют элементы, которые сведены в табл. 24.7.
    Таблица 24.7. Операции в трейте mutable .Set
    Что
    Что делает
    Добавления
    xs += x
    (или xs.addOne(x)
    )
    Добавляет элемент x
    в множество xs как побочный эффект и возвращает само множество xs xs ++= ys
    (или xs.addAll(ys)
    )
    Добавляет все элементы ys в множество xs как по­
    бочный эффект и возвращает само множество xs

    532 Глава 24 • Углубленное изучение коллекций
    Что
    Что делает
    xs.add(x)
    Добавляет элемент x
    в xs и возвращает true
    , если x
    прежде не был в множестве, или false
    , если уже был
    Удаления
    xs –= x
    (или xs.subtractOne(x)
    )
    Удаляет элемент x
    из множества xs как побочный эффект и возвращает само множество xs xs ––= ys
    (или xs.subtractAll(ys)
    )
    Удаляет все элементы ys из множества xs как побоч­
    ный эффект и возвращает само множество xs xs.remove(x)
    Удаляет элемент x
    из xs и возвращает true
    , если x
    прежде уже был в множестве, или false
    , если его прежде там не было xs.filterInPlace(p)
    Сохраняет только те элементы в xs
    , которые удов­
    летворяют условию p
    xs.clear()
    Удаляет из xs все элементы
    Обновление
    xs(x) = b
    (или после раскрытия xs.update(x,
    b)
    )
    Если аргумент b
    типа
    Boolean имеет значение true
    , то добавляет x
    в xs
    , в противном случае удаляет x
    из xs
    Клонирование
    xs.clone()
    Возвращает новое изменяемое множество с такими же элементами, как и в xs
    Операция s
    +=
    elem в качестве побочного эффекта добавляет elem во множе­
    ство s
    и в качестве результата возвращает измененное множество. По ана­
    логии с этим s
    -=
    elem удаляет элемент elem из множества и возвращает в качестве результата измененное множество. Помимо
    +=
    и
    -=
    , есть также операции над несколькими элементами
    ++=
    и
    --=
    , которые добавляют или удаляют все элементы
    Iterable или итератора.
    Выбор в качестве имен методов
    +=
    и
    -=
    означает, что очень похожий код может работать как с изменяемыми, так и с неизменяемыми множествами.
    Рассмотрим сначала следующий интерпретатор, в котором используется неизменяемое множество s
    :
    var s = Set(1, 2, 3)
    s += 4
    s = 2
    s // Set(1, 3, 4)
    Таблица 24.7 (окончание)

    24 .5 . Множества 533
    В этом примере в отношении var
    ­переменной типа immutable.Set использу­
    ются методы
    +=
    и
    -=
    . Согласно объяснениям, которые были даны в шаге 10 главы 3, инструкции вида s
    +=
    4
    — это сокращенная форма записи для s
    =
    s
    +
    4
    . Следовательно, в их выполнении участвует еще один метод
    +
    , применяемый в отношении множества s
    , а затем результат присваивается переменной s
    . А теперь рассмотрим аналогичную работу в интерпретаторе с изменяемым множеством:
    val s = collection.mutable.Set(1, 2, 3)
    s += 4 // Set(1, 2, 3, 4)
    s = 2 // Set(1, 3, 4)
    s // Set(1, 3, 4)
    Конечный эффект очень похож на предыдущий диалог с интерпретатором: начинаем мы с множеством
    Set(1,
    2,
    3)
    , а заканчиваем с множеством
    Set(1,
    3,
    4)
    . Но даже притом что инструкции выглядят такими же, как и раньше, они выполняют несколько иные действия. Теперь инструкция s
    +=
    4
    вызыва­
    ет метод
    +=
    в отношении значения s
    , которое представляет собой изменяемое множество, выполняя изменения на месте. Аналогично этому инструкция s
    -=
    2
    теперь вызывает в отношении этого же множества метод
    -=
    Сравнение этих двух диалогов позволяет выявить весьма важный принцип.
    Зачастую можно заменить изменяемую коллекцию, хранящуюся в val
    ­
    переменной, неизменяемой коллекцией, хранящейся в var
    ­переменной, и наоборот. Это работает по крайней мере до тех пор, пока нет псевдонимов ссылок на коллекцию, позволяющих заметить, обновилась она на месте или была создана новая коллекция.
    Изменяемые множества также предоставляют в качестве вариантов
    +=
    и
    -=
    методы add и remove
    . Разница в том, что методы add и remove возвращают булев результат, показывающий, возымела ли операция эффект над множе­
    ством.
    В текущей реализации по умолчанию изменяемого множества его элементы хранятся с помощью хеш­таблицы. В реализации по умолчанию неизменя­
    емых множеств используется представление, которое адаптируется к ко­
    личеству элементов множества. Пустое множество представляется в виде простого объекта­одиночки. Множества размером до четырех элементов представляются в виде одиночного объекта, сохраняющего все элементы как поля. Все неизменяемые множества, имеющие большие размеры, реализуют­
    ся в виде сжатых хеш­массивов из сопоставленных префиксных деревьев
    1 1
    Префиксные деревья на основе сжатых хеш­массивов описываются в разделе 24.7.

    534 Глава 24 • Углубленное изучение коллекций
    Последствия применения таких вариантов представления заключаются в том, что для множеств небольших размеров с количеством элементов, не превышающим четырех, неизменяемые множества получаются более ком­
    пактными и более эффективными в работе, чем изменяемые. Поэтому, если предполагается, что множество будет небольшим, попробуйте сделать его неизменяемым.
    24 .6 . Отображения
    Коллекции типа
    Map представляют собой
    Iterable
    ­коллекции, состоящие из пар «ключ — значение», которые также называются отображениями или ассоциациями. Объект
    Predef в Scala предлагает неявное преобразование, позволяющее использовать запись вида
    ключ
    –>
    значение
    в качестве альтерна­
    тивы синтаксиса для пары вида
    (ключ,
    значение)
    . Таким образом, выражение для инициализации
    Map("x"
    –>
    24,
    "y"
    –>
    25,
    "z"
    –>
    26)
    означает абсолютно то же самое, что и выражение
    Map(("x",
    24),
    ("y",
    25),
    ("z",
    26))
    , но чи­
    тается легче.
    Основные операции над отображениями, сведенные в табл. 24.8, похожи на аналогичные операции над множествами. Неизменяемые отображения под­
    держивают дополнительные операции добавления и удаления, которые воз­
    вращают новые отображения, как показано в табл. 24.9. Изменяемые отобра­
    жения дополнительно поддерживают операции, перечисленные в табл. 24.10.
    Операции над отображениями разбиваются на следующие категории.
    z z
    Операции поиска apply, get, getOrElse, contains и isDefinedAt превра­
    щают отображения в частично примененные функции от ключей к значе­
    ниям. Основной метод поиска для отображений выглядит так:
    def get(key): Option[Value]
    Операция m.get(key)
    проверяет, содержит ли отображение ассоциацию для заданного ключа. Будучи в наличии, такая ассоциация возвращает значение ассоциации в виде объекта типа
    Some
    . Если такой ключ в ото­
    бражении не определен, то get возвращает
    None
    . В отображениях также определяется метод apply
    , возвращающий значение, непосредственно ассоциированное с заданным ключом, без его инкапсуляции в
    Option
    Если ключ в отображении не определен, то выдается исключение.
    z z
    Добавления и обновления + (псевдоним: updated), ++ (псевдоним:
    concat) updateWith и updatedWith позволяют добавлять к отображению новые привязки или изменять уже существующие.

    24 .6 . Отображения 535
    z z
    Удаления - (псевдоним: removed) и -- (псевдоним: removedAll) позво­
    ляют удалять привязки из отображения.
    z z
    Операции создания подколлекций keys, keySet, keysIterator, valu-
    esIterator и values возвращают по отдельности ключи и значения ото­
    бражений в различных формах.
    z z
    Преобразования filterKeys и mapValues создают новое отображение путем фильтрации и преобразования привязок существующего отображения.
    Таблица 24.8. Операции в трейте Map
    Что
    Что делает
    Поиск
    ms.get(k)
    Значение
    Option
    , связанное с ключом k
    в отображе­
    нии ms
    , или
    None
    , если ключ не найден ms(k)
    (или после рас­
    крытия ms apply k
    )
    Значение, связанное с ключом k
    в отображении ms
    , или выдает исключение, если ключ не найден ms.getOrElse(k, d)
    Значение, связанное с ключом k
    в отображении ms
    , или значение по умолчанию d
    , если ключ не найден ms.contains(k)
    Проверяет, содержится ли в ms отображение для ключа k
    ms.isDefinedAt(k)
    То же, что и contains
    Создание подколлекций
    ms.keys
    Iterable­коллекция, содержащая каждый ключ, име­
    ющийся в ms ms.keySet
    Множество, содержащее каждый ключ, имеющийся в ms ms.keysIterator
    Итератор, выдающий каждый ключ, имеющийся в ms ms.values
    Iterable­коллекция, содержащая каждое значение, связанное с ключом в ms ms.valuesIterator
    Итератор, выдающий каждое значение, связанное с ключом в ms
    Преобразования
    ms.view.filterKeys(p)
    Представление отображения, содержащее только те отображения в ms
    , в которых ключ удовлетворяет условию p
    ms.view.mapValues(f)
    Представление отображения, получающееся в резуль­
    тате применения функции f
    к каждому значению, связанному с ключом в ms

    536 Глава 24 • Углубленное изучение коллекций
    Таблица 24.9. Операции в трейте immutable .Map
    Что
    Что делает
    Добавления и обновления
    ms + (k –> v)
    (или ms.updated(k, v)
    )
    Отображение, содержащее все ассоциации ms
    , а также ассоциацию k –> v ключа k
    со значением v
    ms ++= kvs
    (или ms.concat(kvs)
    )
    Отображение, содержащее все ассоциации ms
    , а также все пары «ключ — значение» из kvs ms.updatedWith(k)(f)
    Отображение с добавлением, обновлением или уда­
    лением привязки для ключа k
    . Функция f
    принимает в качестве параметра значение, связанное в настоя­
    щий момент с ключом k
    (или
    None
    , если такой привяз­
    ки нет), и возвращает новое значение (или
    None для удаления привязки)
    Удаления
    ms – k
    (или ms.removed(k)
    )
    Отображение, содержащее все ассоциации ms
    , за ис­
    ключением тех, которые относятся к ключу k
    ms –– ks
    (или ms.removedAll(ks)
    )
    Отображение, содержащее все ассоциации ms
    , за ис­
    ключением тех, ключи которых входят в ks
    Таблица 24.10. Операции в трейте mutable .Map
    Что
    Что делает
    Добавления и обновления
    ms(k)
    =
    v
    (или после рас­
    крытия ms.update(k,
    v)
    )
    Добавляет в качестве побочного эффекта ассо­
    циацию ключа k
    со значением v
    к отображе­
    нию ms
    , перезаписывая все ранее имевшиеся ассоциации k
    ms
    +=
    (k
    –>
    v)
    Добавляет в качестве побочного эффекта ассоциа­
    цию ключа k
    со значением v
    к отображению ms и возвращает само отображение ms ms
    ++=
    kvs
    Добавляет в качестве побочного эффекта все ассо­
    циации, имеющиеся в kvs
    , к ms и возвращает само отображение ms ms.put(k,
    v)
    Добавляет к ms ассоциацию ключа k
    со значением v
    и возвращает как Option любое значение, ранее связанное с k
    ms.getOrElseUpdate(k,
    d)
    Если ключ k
    определен в отображении ms
    , то воз­
    вращает связанное с ним значение. В противном случае обновляет ms ассоциацией k –> d и возвра­
    щает d

    24 .6 . Отображения 537
    Что
    Что делает
    ms.updateWith(k)(f)
    Добавляет, обновляет или удаляет ассоциацию с ключом k
    . Функция f
    принимает в качестве параметра значение, которое в настоящий момент связано с k
    (или
    None
    , если такой ассоциации нет), и возвращает новое значение (или
    None t
    при удале­
    нии ассоциации)
    Удаления
    ms
    –=
    k
    Удаляет в качестве побочного эффекта ассоциацию с ключом k
    из ms и возвращает само отображение ms ms
    ––=
    ks
    Удаляет в качестве побочного эффекта все ассоциа­
    ции из ms с ключами, имеющимися в ks
    , и возвраща­
    ет само отображение ms ms.remove(k)
    Удаляет все ассоциации с ключом k
    из ms и воз­
    вращает как Option любое значение, ранее связан­
    ное с k
    ms.filterInPlace(p)
    Сохраняет в ms только те ассоциации, у которых ключ удовлетворяет условию p
    ms.clear()
    Удаляет из ms все ассоциации
    Преобразование и клонирование
    ms.mapValuesInPlace(f)
    Выполняет преобразование всех связанных значе­
    ний в отображении ms с помощью функции f
    ms.clone()
    Возвращает новое изменяемое отображение с таки­
    ми же ассоциациями, как и в ms
    Операции добавления и удаления для отображений — зеркальные отражения таких же операций для множеств. Неизменяемое отображение может быть преобразовано с помощью операций
    +
    ,
    - и updated
    . Для сравнения: изменя­
    емое отображение m
    можно обновить «на месте» двумя способами: m(key)
    =
    value и m
    +=
    (key
    –>
    value)
    . Изменяемые отображения также поддерживают вариант m.put(key,
    value)
    , который возвращает значение
    Option
    , содержа­
    щее то, что прежде ассоциировалось с ключом, или
    None
    , если ранее такой ключ в отображении отсутствовал.
    Метод getOrElseUpdate пригодится для обращения к отображениям там, где они действуют в качестве кэша. Скажем, у вас есть весьма затратное вычис­
    ление, запускаемое путем вызова функции f
    :
    def f(x: String) =
    println("taking my time.")
    Thread.sleep(100)
    x.reverse

    538 Глава 24 • Углубленное изучение коллекций
    Далее предположим, что у f
    нет побочных эффектов, поэтому ее повторный вы­
    зов с тем же самым аргументом всегда будет выдавать тот же самый результат.
    В таком случае можно сберечь время, сохранив ранее вычисленные привязки аргумента и результата выполнения f
    в отображении, и вычислять результат выполнения f
    , только если результат для аргумента не был найден в отображе­
    нии. Можно сказать, что отображение — это кэш для вычислений функции f
    :
    val cache = collection.mutable.Map[String, String]()
    Теперь можно создать более эффективную кэшированную версию функ­
    ции f
    :
    scala> def cachedF(s: String) = cache.getOrElseUpdate(s, f(s))
    def cachedF(s: String): String scala> cachedF("abc")
    taking my time.
    val res16: String = cba scala> cachedF("abc")
    val res17: String = cba
    Обратите внимание: второй аргумент getOrElseUpdate
    — это аргумент, пере­
    даваемый по имени. Следовательно, показанное ранее вычисление f("abc")
    выполняется лишь в том случае, если методу getOrElseUpdate потребуется значение его второго аргумента, что происходит именно тогда, когда его первый аргумент не найден в кэширующем отображении. Вы могли бы также непосредственно реализовать cachedF
    , используя только основные операции с отображениями, но для этого понадобится дополнительный код:
    def cachedF(arg: String) =
    cache.get(arg) match case Some(result) => result case None =>
    val result = f(arg)
    cache(arg) = result result
    24 .7 . Конкретные классы неизменяемых коллекций
    В Scala на выбор предлагается множество конкретных классов неизменя­
    емых коллекций. Друг от друга они отличаются реализуемыми трейтами
    (отображения, множества, последовательности) тем, могут ли они быть бес­

    24 .7 . Конкретные классы неизменяемых коллекций
    1   ...   52   53   54   55   56   57   58   59   ...   64


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