1. 概述

在这个简短的教程中,我们将学习如何在使用List接口提供的subList()方法时避免IndexOutOfBoundsException。首先,我们将讨论subList()的工作原理,然后在实践中看到如何重现并修复这个异常。

2. 了解异常

通常,Collections API提供了subList(int fromIndex, int toIndex)方法,用于返回给定列表的一部分。返回的部分包括指定的fromIndextoIndex之间的所有元素。需要注意的是,fromIndex始终是包含的,而toIndex则是不包含的。

subList()方法的特性是,当给定的fromIndexendIndex有问题时,会抛出IndexOutOfBoundsException作为信号。

简单来说,IndexOutOfBoundsException意味着越界,当fromIndex严格小于0、严格大于toIndex,或者toIndex大于列表长度时,就会抛出这个异常。

3. 实践示例

现在让我们看看subList()方法的实际应用。为了简化,我们创建一个测试来重现IndexOutOfBoundsException

@Test
void whenCallingSuListWithIncorrectIndexes_thenThrowIndexOutOfBoundsException() {
    List<String> cities = List.of("Tokyo", "Tamassint", "Paris", "Madrid", "London");

    assertThatThrownBy(() -> cities.subList(6, 10)).isInstanceOf(IndexOutOfBoundsException.class);
}

如图所示,测试因为提供了一个大于列表长度的toIndex参数(10)而失败,抛出了IndexOutOfBoundsException

4. 解决异常

修复异常最简单的方法是在调用subList()方法之前对指定的fromIndextoIndex进行验证:

static List<String> safeSubList(List<String> myList, int fromIndex, int toIndex) {

    if (myList == null || fromIndex >= myList.size() || toIndex <= 0 || fromIndex >= toIndex) {
        return Collections.emptyList();
    }

    return myList.subList(Math.max(0, fromIndex), Math.min(myList.size(), toIndex));
}

如上所示,我们的替代方法是安全的。如果给定的fromIndex大于或等于列表大小或给定的toIndex,则返回空列表。同样,如果指定的toIndex小于或等于0,也返回空列表。如果fromIndex小于0,我们将0作为fromIndex参数传递。另一方面,如果传递的toIndex参数大于列表大小,我们将设置列表大小为新的toIndex

现在,让我们添加另一个测试用例来验证我们的新方法是否有效:

@Test
void whenCallingSafeSuList_thenReturnData() {
    List<String> cities = List.of("Amsterdam", "Buenos Aires", "Dublin", "Brussels", "Prague");

    assertThat(SubListUtils.safeSubList(cities, 6, 10)).isEmpty();
    assertThat(SubListUtils.safeSubList(cities, -2, 3)).containsExactly("Amsterdam", "Buenos Aires", "Dublin");
    assertThat(SubListUtils.safeSubList(cities, 3, 20)).containsExactly("Brussels", "Prague");
}

正如预期的那样,我们的subList()方法的安全版本可以处理任何指定的fromIndextoIndex

5. 总结

在这篇短文中,我们讨论了如何在使用subList()方法时避免IndexOutOfBoundsException。过程中,我们了解了导致subList()抛出异常的原因,并学会了如何在实践中重现和修复它。如往常一样,示例的完整源代码可以在GitHub上找到。