【发布时间】:2011-01-18 08:27:21
【问题描述】:
有谁知道,为什么AbstractList(以及ArrayList)中的 removeRange 方法是protected?它看起来像是一个定义明确且有用的操作,但要使用它,我们还是不得不继承 List 实现。
有什么隐藏的理由吗?对我来说似乎很莫名。
【问题讨论】:
标签: java list collections arraylist protected
有谁知道,为什么AbstractList(以及ArrayList)中的 removeRange 方法是protected?它看起来像是一个定义明确且有用的操作,但要使用它,我们还是不得不继承 List 实现。
有什么隐藏的理由吗?对我来说似乎很莫名。
【问题讨论】:
标签: java list collections arraylist protected
是的,因为这不是您从外部代码中删除范围的方式。相反,请这样做:
list.subList(start, end).clear();
这实际上在幕后调用removeRange。†
OP 询问为什么 removeRange 不是 List 公共 API 的一部分。原因在 Effective Java 2nd ed 的 Item 40 中有描述,我在这里引用它:
有三种技术可以缩短过长的参数列表。一种是将方法分解为多个方法,每个方法只需要参数的一个子集。如果不小心,这可能会导致方法过多,但也可以通过增加正交性来帮助减少方法数。例如,考虑
java.util.List接口。它不提供在子列表中查找元素的第一个或最后一个索引的方法,这两个方法都需要三个参数。相反,它提供了subList方法,该方法接受两个参数并返回子列表的view。此方法可以与indexOf或lastIndexOf方法结合使用,每个方法都有一个参数,以产生所需的功能。此外,subList方法可以与在List实例上操作的 any 方法组合,以对子列表执行任意计算。生成的 API 具有非常高的功率重量比。
有人可能会争辩说removeRange 没有那么多参数,因此可能不适合这种处理方式,但鉴于有一种方法可以通过subList 调用removeRange,因此没有理由使用冗余方法使List 接口混乱。
†AbstractList.removeRange 文档说:
此方法由对此列表及其子列表的
clear操作调用。重写此方法以利用列表实现的内部结构可以显着提高此列表及其子列表上的clear操作的性能。
另外,请参阅 OpenJDK 对 AbstractList.clear 和 SubList.removeRange 的实现。
【讨论】:
removeRange 不必要地调用arraycopy 当ArrayList 版本用于跨越到列表最后的范围? hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/e2117e30fb39/src/share/… numMoved 为 0,因此整个 arraycopy 代码可以放入单个 if(如 remove 中所做的那样);不同之处在于 a) arraycopy 是本机调用,会产生开销,b) arraycopy 总是 检查参数的正确性stackoverflow.com/questions/12594046/…