What version of OpenRewrite are you using?
- rewrite-migrate-java: 3.35.0
- rewrite-core: 8.83.2
- rewrite-java: 8.83.2
What is the smallest, simplest way to reproduce the problem?
import java.util.LinkedHashMap;
import java.util.Map;
class Main {
static final Map<String, String> ORDERED =
new LinkedHashMap<>() {
{
put("a", "1");
put("b", "2");
put("c", "3");
}
};
}
Run org.openrewrite.java.migrate.util.UseMapOf.
What did you expect to see?
No change. LinkedHashMap guarantees insertion-order iteration, whereas Map.of(...) makes no ordering guarantee at all (the iteration order of the immutable maps returned by Map.of is explicitly unspecified and is in fact deliberately randomized per JVM instance). Converting LinkedHashMap (or TreeMap) to Map.of silently drops the ordering contract that the original code relied on.
UseMapOf should only apply to map implementations whose iteration order is already unspecified (i.e. java.util.HashMap). It should skip order-sensitive implementations such as LinkedHashMap and TreeMap.
What did you see instead?
The recipe rewrites the order-preserving LinkedHashMap to Map.of, discarding the insertion-order guarantee:
import java.util.LinkedHashMap;
import java.util.Map;
class Main {
static final Map<String, String> ORDERED =
Map.of(
"a", "1",
"b", "2",
"c", "3");
}
Any code iterating over ORDERED (e.g. serializing it to YAML/JSON, or driving an ordered rollout) now observes an arbitrary, run-to-run-varying order. This is a behavioral change, not a refactoring, and it compiles cleanly so it passes silently until runtime.
(The unused LinkedHashMap import is also left behind, but the ordering regression is the substantive problem.)
What is the full stack trace of any errors you encountered?
No error: the transformation produces compiling code with changed runtime semantics. The regression surfaces downstream as a failing test or incorrect ordering at runtime.
What version of OpenRewrite are you using?
What is the smallest, simplest way to reproduce the problem?
Run
org.openrewrite.java.migrate.util.UseMapOf.What did you expect to see?
No change.
LinkedHashMapguarantees insertion-order iteration, whereasMap.of(...)makes no ordering guarantee at all (the iteration order of the immutable maps returned byMap.ofis explicitly unspecified and is in fact deliberately randomized per JVM instance). ConvertingLinkedHashMap(orTreeMap) toMap.ofsilently drops the ordering contract that the original code relied on.UseMapOfshould only apply to map implementations whose iteration order is already unspecified (i.e.java.util.HashMap). It should skip order-sensitive implementations such asLinkedHashMapandTreeMap.What did you see instead?
The recipe rewrites the order-preserving
LinkedHashMaptoMap.of, discarding the insertion-order guarantee:Any code iterating over
ORDERED(e.g. serializing it to YAML/JSON, or driving an ordered rollout) now observes an arbitrary, run-to-run-varying order. This is a behavioral change, not a refactoring, and it compiles cleanly so it passes silently until runtime.(The unused
LinkedHashMapimport is also left behind, but the ordering regression is the substantive problem.)What is the full stack trace of any errors you encountered?
No error: the transformation produces compiling code with changed runtime semantics. The regression surfaces downstream as a failing test or incorrect ordering at runtime.