---
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/en/llms.txt

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

StateAccessor is an interface for reading, modifying, and deleting state values. For general information about stateful processing, see the [Stateful processing](https://ytsaurus.tech/docs/en/flow/concepts/stateful.md) section.

## How it works {#how-it-works}

The [state](https://ytsaurus.tech/docs/en/flow/concepts/glossary.md#state) in Flow is stored in [sorted dynamic tables](https://ytsaurus.tech/docs/en/user-guide/dynamic-tables/sorted-dynamic-tables.md).
If you use [external state](https://ytsaurus.tech/docs/en/flow/java/external-state.md), you create this table. If you use [internal state](https://ytsaurus.tech/docs/en/flow/java/internal-state.md), Flow creates and manages these tables automatically.

For simplicity, the following description focuses on an example with external state.

You can think of each row in the state table as having two parts: key columns and value columns:

<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>

For `TTransformCompanionComputation`, the key columns in the state table match the `group_by_schema` of the [computation](https://ytsaurus.tech/docs/en/flow/concepts/glossary.md#stream-and-computation). For the internal state of `TTransformOrderedSourceCompanionComputation`, the source partition key is used instead; this SourceComputation does not support `group_by_schema`.

The value columns are available for reading and modifying through `StateAccessor`. The format in which you can read and modify these values in Java code depends on the `StateAccessor` implementation.

## Reading and writing data {#reading-and-writing-data}

The [worker](https://ytsaurus.tech/docs/en/flow/concepts/glossary.md#worker) handles direct operations on the table, including reading, writing, and deleting data. When the worker receives the next batch of [messages](https://ytsaurus.tech/docs/en/flow/concepts/glossary.md#message), it loads the state values for all [keys](https://ytsaurus.tech/docs/en/flow/concepts/glossary.md#key) in the batch and sends them to the [companion](https://ytsaurus.tech/docs/en/flow/concepts/companion.md) along with the messages and [timers](https://ytsaurus.tech/docs/en/flow/concepts/glossary.md#timer). For more details, see the [interaction schema](https://ytsaurus.tech/docs/en/flow/concepts/companion.md#schema).

You write new values to the state table as a transaction within an [epoch](https://ytsaurus.tech/docs/en/flow/concepts/glossary.md#epoch).

## StateAccessor interface {#state-accessor-interface}

{% list tabs group=lang %}

- Java

  ```java
  public interface StateAccessor<T> {
      /** Get the state value. */
      @Nullable
      T get();

      /** Get the state value or a default value. */
      default T getOrDefault(T defaultValue);

      /** Set the state value. */
      void set(T value);

      /** Clear or delete the state for the key. */
      void clear();

      /** Get the state class. */
      Class<T> getStateClass();

      /** Get a read-only view of the accessor. */
      default StateAccessor<T> readOnly();
  }
  ```

- Kotlin

  ```kotlin
  interface StateAccessor<T> {
      /** Get the state value. */
      fun get(): T?

      /** Get the state value or a default value. */
      fun getOrDefault(defaultValue: T): T

      /** Set the state value. */
      fun set(value: T)

      /** Clear or delete the state for the key. */
      fun clear()

      /** Get the state class. */
      fun getStateClass(): Class<T>

      /** Get a read-only view of the accessor. */
      fun readOnly(): StateAccessor<T>
  }
  ```

{% endlist %}

The value of an internal state returned by `get()` and `getOrDefault()` is live: the changes made to it are written without a `set()` call, and `readOnly()` returns an untracked view — see [Changing the value in place](https://ytsaurus.tech/docs/en/flow/java/internal-state.md#in-place). A default returned by `getOrDefault()` is not written to YTsaurus: it becomes the state value only if the computation changes it.
<!-- endsource: en/_includes/flow/java/state-accessor.md -->
