This test fails when added to DataBinderConstructTests.java:

    @Test
    void listBindingWithNonconsecutiveIndices() {
        MapValueResolver valueResolver = new MapValueResolver(Map.of(
                "dataClassList[0].param1", "value1", "dataClassList[0].param2", "true",
                "dataClassList[1].param1", "value2", "dataClassList[1].param2", "true",
                "dataClassList[3].param1", "value3", "dataClassList[3].param2", "true"));

        DataBinder binder = initDataBinder(ListDataClass.class);
        binder.construct(valueResolver);

        ListDataClass dataClass = getTarget(binder);
        List<DataClass> list = dataClass.dataClassList();

        assertThat(list.get(0).param1()).isEqualTo("value1");
        assertThat(list.get(1).param1()).isEqualTo("value2");
        assertThat(list.get(3).param1()).isEqualTo("value3");
    }

The stack trace looks like this:

Index 3 out of bounds for length 3
java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
    at java.base/java.util.Objects.checkIndex(Objects.java:361)
    at java.base/java.util.ArrayList.set(ArrayList.java:441)
    at org.springframework.validation.DataBinder.createList(DataBinder.java:1039)
    at org.springframework.validation.DataBinder.createObject(DataBinder.java:936)
    at org.springframework.validation.DataBinder.construct(DataBinder.java:885)
    at org.springframework.validation.DataBinderConstructTests.listBindingWithNonconsecutiveIndices(DataBinderConstructTests.java:132)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

I think the problem is with this line in DataBinder.createList():

indexes.forEach(i -> list.add(null));

In order to support nonconsecutive indices, it would need to create enough elements to match the value of highest index, but it's instead creating enough elements to match the count of indices that were submitted.

Comment From: rstoyanchev

Thanks for the analysis and test. Yes, we should be going by the calculated size rather than the number of indexes.