Collection Element Replaced Without Being Read

ID

java.no_unconditional_element_replace

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Java

Tags

collection, dead-code, reliability

Description

Reports two consecutive statements in the same block that store to the same map key or array index with no intervening read of it: map.put(k, ..) twice with the same receiver and the same literal-or-symbol key, or arr[i] = .. twice with the same array symbol and index.

letters.put("a", "Apple");
letters.put("a", "Boy");     // flagged: "Apple" is discarded, never read

towns[i] = "London";
towns[i] = "Chicago";        // flagged: "London" is discarded, never read

Rationale

The earlier value is overwritten before anyone ever reads it. That is redundant at best — the first store did nothing — and far more often a copy-paste slip that overwrote the wrong key or index, or forgot a condition that should have separated the two stores.

A read of the same key or index between the two stores makes the pair legitimate, including a read embedded in the second store’s own value expression:

arr[i] = arr[i] + 1;   // reads the previous value first
arr[i] = x;             // not flagged: the value above was actually used

Only literal and simple-symbol keys are compared, and only within one flat statement list — a store inside a branch or a loop between the two candidates is not chased into, and a store to a different collection, or under a different key, is left alone.

The receiver must be declared as a java.util.Map (or one of its implementations) in the same method or as a field of the enclosing type. A put that adds rather than replaces is not a defect, and plenty of types spell one that way:

ArrayListMultimap<Field, ValueChecker> checkers = ArrayListMultimap.create();
checkers.put(BOOKTITLE, new BooktitleContainsYearChecker());
checkers.put(BOOKTITLE, new AbbreviationChecker());   // not flagged: Multimap.put appends

Any statement that merely names the collection between the two stores also clears it, a store statement included — passing the map on is how the code under test gets to read it:

objectVar.put("age", 28);
variables.put("objectVar", objectVar);   // objectVar is handed on here
deployAndStart(variables);
objectVar.put("age", 29);                 // not flagged: the first value was read in between

Remediation

Delete the redundant first store, or add whatever condition or read was missing between the two.

letters.put("a", "Apple");
// ... some logic reads letters.get("a") here ...
letters.put("a", "Boy");

© 2026 Xygeni. All rights reserved