Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

LinkedCaseInsensitiveMap.keySet().remove returns false after removing a null-valued entry

オープン 初心者向け
#37,470 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

  • #37478 @zsewasdsdsd による — マージされずにクローズ

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
78/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
java, spring
領域
backend

調査の方向性

バグは spring-core の LinkedCaseInsensitiveMap.java にある内部クラス KeySet にあります。そこでは remove(o) が戻り値の boolean を、Map.remove が null を返したかどうかで決めているため、値が null のエントリでは false が返ります。issue の Repro.java スニペットを spring-core に対して実行し、1行目と3行目が false を出力することを確認してください。keySet().remove と keySet().removeAll が、存在する値 null のキーに対して true を返し、既存の LinkedCaseInsensitiveMap のテストがすべて通れば完了です。

索引モデルが issue の本文から書いたものです。

説明

status: waiting-for-triage
Affected versions

Verified with the published spring-core 7.0.9 and 6.2.19 artifacts on JDK 21. The same result was reproduced with the affected classes compiled from main at 85a532dce455655aec8fd5a301b37c6c5ceda5bb, with the remaining dependencies supplied by spring-core 7.0.9. This was a focused reproduction, not a full Gradle build.

Problem

LinkedCaseInsensitiveMap supports null values. When a key is mapped to null, keySet().remove(key) removes the entry but returns false. This contradicts the Set removal contract, and also makes keySet().removeAll(...) report no change when it chooses its remove-based path.

Callers relying on the boolean result to detect a change receive the wrong result even though the map was modified.

Minimal reproduction

Save as Repro.java:

import java.util.Locale;
import java.util.Set;
import org.springframework.util.LinkedCaseInsensitiveMap;

public class Repro {
    public static void main(String[] args) {
        var map = new LinkedCaseInsensitiveMap<String>(Locale.ROOT);
        map.put("key", null);
        System.out.println(map.keySet().remove("key"));
        System.out.println(map.isEmpty());

        map.put("key", null);
        map.put("other", "value");
        System.out.println(map.keySet().removeAll(Set.of("key")));
        System.out.println(map.containsKey("key"));
        System.out.println(map.size());
    }
}

Run on Java 17 or later:

curl -fLO https://repo.maven.apache.org/maven2/org/springframework/spring-core/7.0.9/spring-core-7.0.9.jar
java -cp spring-core-7.0.9.jar Repro.java

Actual output:

false
true
false
false
1

Expected: the first and third lines should be true, because both operations removed an existing key. The remaining lines are correct.

Cause

LinkedCaseInsensitiveMap.KeySet.remove returns LinkedCaseInsensitiveMap.this.remove(o) != null. A null return from Map.remove cannot distinguish an absent key from a present null-valued mapping.

The Java Set.remove contract requires true when the set contained the element and it was removed.

Related reports checked

#22821 / #23644 addressed stale internal key registrations after collection-view removals. This report concerns the boolean return value after a successful removal; the internal key registration is correctly cleared in this reproduction. #37351 concerns computeIfAbsent registrations and is also a separate case. Searches for LinkedCaseInsensitiveMap keySet and LinkedCaseInsensitiveMap null remove did not reveal a direct duplicate.

主要言語
Java
スター
60.3k
フォーク
38.7k
平均マージ
1日 9時間
マージ済み PR(30日)
34

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

spring-projects/spring-framework のほかの issue

spring-projects/spring-framework の issue をすべて見る

似ている issue

Java の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。