Repository: open-telemetry/opentelemetry-java
File: api/all/src/main/java/io/opentelemetry/api/common/AttributesBuilder.java (Java)

Code before:
import static io.opentelemetry.api.common.AttributeKey.longKey;
import static io.opentelemetry.api.common.AttributeKey.stringArrayKey;
import static io.opentelemetry.api.common.AttributeKey.stringKey;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/** A builder of {@link Attributes} supporting an arbitrary number of key-value pairs. */
public interface AttributesBuilder {
  /** Create the {@link Attributes} from this. */
  Attributes build();

  /**
   * Puts a {@link AttributeKey} with associated value into this.
   *
   * <p>The type parameter is unused.
   */
  // The type parameter was added unintentionally and unfortunately it is an API break for
  // implementations of this interface to remove it. It doesn't affect users of the interface in
  // any way, and has almost no effect on implementations, so we leave it until a future major
  // version.
  <T> AttributesBuilder put(AttributeKey<Long> key, int value);

  /** Puts an {@link AttributeKey} with an associated value into this if the value is non-null. */
  <T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value);

  /**
   * Puts a String attribute into this.
   *
   * <p>Note: It is strongly recommended to use {@link #put(AttributeKey, Object)}, and pre-allocate
   * your keys, if possible.
   *
   * @return this Builder
   */
  default AttributesBuilder put(String key, @Nullable String value) {
    return put(stringKey(key), value);
  }

  /**
   * Puts a long attribute into this.
   *
   * <p>Note: It is strongly recommended to use {@link #put(AttributeKey, Object)}, and pre-allocate
   * your keys, if possible.
   *
   * @return this Builder
   */
  default AttributesBuilder put(String key, long value) {
    return put(longKey(key), value);
  }

Review comment (suggestion):
I might even think an additional comment is useful -- something which conveys that any _existing_ value for that key will remain if null is passed (a null value doesn't remove/unset any current value).

Code after:
import static io.opentelemetry.api.common.AttributeKey.longKey;
import static io.opentelemetry.api.common.AttributeKey.stringArrayKey;
import static io.opentelemetry.api.common.AttributeKey.stringKey;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/** A builder of {@link Attributes} supporting an arbitrary number of key-value pairs. */
public interface AttributesBuilder {
  /** Create the {@link Attributes} from this. */
  Attributes build();

  /**
   * Puts a {@link AttributeKey} with associated value into this.
   *
   * <p>The type parameter is unused.
   */
  // The type parameter was added unintentionally and unfortunately it is an API break for
  // implementations of this interface to remove it. It doesn't affect users of the interface in
  // any way, and has almost no effect on implementations, so we leave it until a future major
  // version.
  <T> AttributesBuilder put(AttributeKey<Long> key, int value);

  /**
   * Puts an {@link AttributeKey} with an associated value into this if the value is non-null.
   * Providing a null value does not remove or unset previously set values.
   */
  <T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value);

  /**
   * Puts a String attribute into this if the value is non-null. Providing a null value does not
   * remove or unset previously set values.
   *
   * <p>Note: It is strongly recommended to use {@link #put(AttributeKey, Object)}, and pre-allocate
   * your keys, if possible.
   *
   * @return this Builder
   */
  default AttributesBuilder put(String key, @Nullable String value) {
    return put(stringKey(key), value);
  }

  /**
   * Puts a long attribute into this.
   *
   * <p>Note: It is strongly recommended to use {@link #put(AttributeKey, Object)}, and pre-allocate
   * your keys, if possible.
   *
   * @return this Builder