---
metadata:
  - name: generator
    content: Diplodoc Platform v5.50.6
alternate:
  - https://ytsaurus.tech/docs/en/flow/java/state-accessor.md
  - https://ytsaurus.tech/docs/ru/flow/java/state-accessor.md
---
> **Documentation Index:** Fetch the complete configuration index at https://ytsaurus.tech/docs/ru/llms.txt

<!-- source: ru/_includes/flow/java/state-accessor.md -->
# StateAccessor в YTsaurus Flow (Java)

StateAccessor — интерфейс для чтения, модификации и удаления значений [стейта](https://ytsaurus.tech/docs/ru/flow/concepts/glossary.md#state).
Общие сведения о stateful-обработке описаны в разделе [Stateful processing](https://ytsaurus.tech/docs/ru/flow/concepts/stateful.md).

## Принцип работы {#how-it-works}

[Стейт](https://ytsaurus.tech/docs/ru/flow/concepts/glossary.md#state) во Flow хранится в [сортированных динамических таблицах](https://ytsaurus.tech/docs/ru/user-guide/dynamic-tables/sorted-dynamic-tables.md).
В случае [внешнего стейта](https://ytsaurus.tech/docs/ru/flow/java/external-state.md) эта таблица создаётся пользователем, в случае [внутреннего стейта](https://ytsaurus.tech/docs/ru/flow/java/internal-state.md) эти таблицы создаются и управляются Flow автоматически.

Далее для простоты описания будем рассматривать пример внешнего стейта.

Каждую строку в таблице стейта можно условно разделить на ключевые колонки и колонки значений:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 822.236495593389 163.49380883295362" width="1644.472991186778" height="326.98761766590724"><metadata/><defs></defs><rect x="0" y="0" width="822.236495593389" height="163.49380883295362" fill="#ffffff"/><g stroke-linecap="round" transform="translate(10 69.72291861187205) rotate(0 74.40625 41.826171875)"><path d="M0 0 L148.81 0 L148.81 83.65 L0 83.65" stroke="none" stroke-width="0" fill="#b2f2bb"/><path d="M0 0 C50.97 0, 101.94 0, 148.81 0 M0 0 C42.47 0, 84.93 0, 148.81 0 M148.81 0 C148.81 32.36, 148.81 64.73, 148.81 83.65 M148.81 0 C148.81 23.9, 148.81 47.81, 148.81 83.65 M148.81 83.65 C117.13 83.65, 85.45 83.65, 0 83.65 M148.81 83.65 C113.1 83.65, 77.4 83.65, 0 83.65 M0 83.65 C0 59.64, 0 35.62, 0 0 M0 83.65 C0 55.78, 0 27.9, 0 0" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(60.19628143310547 99.04909048687205) rotate(0 24.20996856689453 12.5)"><text x="24.20996856689453" y="19.08" font-family="Nunito, sans-serif, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic"> hash</text></g><g stroke-linecap="round" transform="translate(158.99382484360876 69.84146508295362) rotate(0 74.40625 41.826171875)"><path d="M0 0 L148.81 0 L148.81 83.65 L0 83.65" stroke="none" stroke-width="0" fill="#b2f2bb"/><path d="M0 0 C29.79 0, 59.58 0, 148.81 0 M0 0 C53.23 0, 106.47 0, 148.81 0 M148.81 0 C148.81 27.69, 148.81 55.38, 148.81 83.65 M148.81 0 C148.81 24.43, 148.81 48.87, 148.81 83.65 M148.81 83.65 C111.32 83.65, 73.82 83.65, 0 83.65 M148.81 83.65 C113.3 83.65, 77.78 83.65, 0 83.65 M0 83.65 C0 63.47, 0 43.29, 0 0 M0 83.65 C0 58.4, 0 33.15, 0 0" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(207.38010108872595 99.16763695795362) rotate(0 26.019973754882812 12.5)"><text x="26.019973754882812" y="19.08" font-family="Nunito, sans-serif, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic"> word</text></g><g stroke-linecap="round" transform="translate(307.33366859360876 69.84146508295362) rotate(0 74.40625 41.826171875)"><path d="M0 0 L148.81 0 L148.81 83.65 L0 83.65" stroke="none" stroke-width="0" fill="#a5d8ff"/><path d="M0 0 C43.47 0, 86.95 0, 148.81 0 M0 0 C42.89 0, 85.78 0, 148.81 0 M148.81 0 C148.81 21.56, 148.81 43.13, 148.81 83.65 M148.81 0 C148.81 28.11, 148.81 56.22, 148.81 83.65 M148.81 83.65 C111.41 83.65, 74 83.65, 0 83.65 M148.81 83.65 C110.13 83.65, 71.46 83.65, 0 83.65 M0 83.65 C0 53.92, 0 24.19, 0 0 M0 83.65 C0 60.83, 0 38, 0 0" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(354.02995002671423 99.16763695795362) rotate(0 27.70996856689453 12.5)"><text x="27.70996856689453" y="19.08" font-family="Nunito, sans-serif, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic"> count</text></g><g stroke-linecap="round" transform="translate(604.8107143433886 69.80404973739405) rotate(0 103.71289062500023 41.826171875)"><path d="M0 0 L207.43 0 L207.43 83.65 L0 83.65" stroke="none" stroke-width="0" fill="#e9ecef"/><path d="M0 0 C57.6 0, 115.21 0, 207.43 0 M0 0 C65.79 0, 131.59 0, 207.43 0 M207.43 0 C207.43 18.45, 207.43 36.9, 207.43 83.65 M207.43 0 C207.43 17.82, 207.43 35.64, 207.43 83.65 M207.43 83.65 C155.77 83.65, 104.1 83.65, 0 83.65 M207.43 83.65 C164.65 83.65, 121.88 83.65, 0 83.65 M0 83.65 C0 52.54, 0 21.42, 0 0 M0 83.65 C0 61.49, 0 39.33, 0 0" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(627.6837078126268 99.13022161239405) rotate(0 80.83989715576172 12.5)"><text x="80.83989715576172" y="19.08" font-family="Nunito, sans-serif, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic"> system attributes</text></g><g transform="translate(102.26357790374595 10.043570368875407) rotate(0 57.23994445800781 12.5)"><text x="57.23994445800781" y="19.08" font-family="Nunito, sans-serif, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Key columns</text></g><g stroke-linecap="round" transform="translate(456.4444833591706 69.74985619817653) rotate(0 74.40625 41.826171875)"><path d="M0 0 L148.81 0 L148.81 83.65 L0 83.65" stroke="none" stroke-width="0" fill="#a5d8ff"/><path d="M0 0 C46.11 0, 92.23 0, 148.81 0 M0 0 C38.22 0, 76.44 0, 148.81 0 M148.81 0 C148.81 30.21, 148.81 60.43, 148.81 83.65 M148.81 0 C148.81 24.88, 148.81 49.76, 148.81 83.65 M148.81 83.65 C104.95 83.65, 61.09 83.65, 0 83.65 M148.81 83.65 C102.78 83.65, 56.75 83.65, 0 83.65 M0 83.65 C0 66.91, 0 50.17, 0 0 M0 83.65 C0 51.36, 0 19.07, 0 0" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(501.55076845438543 99.07602807317653) rotate(0 29.299964904785156 12.5)"><text x="29.299964904785156" y="19.08" font-family="Nunito, sans-serif, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">length</text></g><g transform="translate(389.2378066337342 10) rotate(0 66.26992797851562 12.5)"><text x="66.26992797851562" y="19.08" font-family="Nunito, sans-serif, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Value columns</text></g></svg>

Для `TTransformCompanionComputation` ключевые колонки в таблице стейта совпадают с `group_by_schema` [компьютейшена](https://ytsaurus.tech/docs/ru/flow/concepts/glossary.md#stream-and-computation). Для внутреннего стейта `TTransformOrderedSourceCompanionComputation` ключом служит ключ партиции источника: `group_by_schema` в таком SourceComputation не поддерживается.

Колонки значений будут доступны для чтения и модификации через `StateAccessor`. Формат, в котором эти значения будут доступны для чтения и модификации в Java-коде, зависит от реализации `StateAccessor`.

## Чтение и запись данных {#reading-and-writing-data}

Непосредственную работу с таблицей (чтение, запись, удаление данных) осуществляет [воркер](https://ytsaurus.tech/docs/ru/flow/concepts/glossary.md#worker). При получении очередного батча [сообщений](https://ytsaurus.tech/docs/ru/flow/concepts/glossary.md#message) воркер загружает значения стейтов для всех [ключей](https://ytsaurus.tech/docs/ru/flow/concepts/glossary.md#key) в батче и отправляет их в [компаньон](https://ytsaurus.tech/docs/ru/flow/concepts/companion.md) вместе с сообщениями и [таймерами](https://ytsaurus.tech/docs/ru/flow/concepts/glossary.md#timer). Подробнее про [схему взаимодействия](https://ytsaurus.tech/docs/ru/flow/concepts/companion.md#schema).

Запись новых значений в таблицу стейта осуществляется транзакционно в рамках [эпохи](https://ytsaurus.tech/docs/ru/flow/concepts/glossary.md#epoch).

## Интерфейс StateAccessor {#state-accessor-interface}

{% list tabs group=lang %}

- Java

  ```java
  public interface StateAccessor<T> {
      /** Получить значение стейта. */
      @Nullable
      T get();

      /** Получить значение стейта или дефолтное значение. */
      default T getOrDefault(T defaultValue);

      /** Установить значение стейта. */
      void set(T value);

      /** Очистить/удалить стейт для ключа. */
      void clear();

      /** Получить класс стейта. */
      Class<T> getStateClass();

      /** Получить read-only представление аксессора. */
      default StateAccessor<T> readOnly();
  }
  ```

- Kotlin

  ```kotlin
  interface StateAccessor<T> {
      /** Получить значение стейта. */
      fun get(): T?

      /** Получить значение стейта или дефолтное значение. */
      fun getOrDefault(defaultValue: T): T

      /** Установить значение стейта. */
      fun set(value: T)

      /** Очистить/удалить стейт для ключа. */
      fun clear()

      /** Получить класс стейта. */
      fun getStateClass(): Class<T>

      /** Получить read-only представление аксессора. */
      fun readOnly(): StateAccessor<T>
  }
  ```

{% endlist %}

Значение внутреннего стейта, полученное через `get()` и `getOrDefault()`, живое: изменения, сделанные в нём, записываются без вызова `set()`, а `readOnly()` возвращает неотслеживаемое представление — см. [Изменение значения на месте](https://ytsaurus.tech/docs/ru/flow/java/internal-state.md#in-place). Дефолт, который вернул `getOrDefault()`, в YTsaurus не записывается: он становится значением стейта, только если вычисление его изменит.
<!-- endsource: ru/_includes/flow/java/state-accessor.md -->
