我有一个应用程序,其中我使用原始数组和列表来创建一个名为Item 的类。由于遗留原因,它们可以互换使用(我也希望这只是一种类型,但它就是这样)。
现在我必须添加一个像这样通过 for-each 循环工作的新方法:
public void something(Item... items) {
for (Item i : items) {
doStuff();
}
}
public void something(List<Item> items) {
for (Item i : items) {
doStuff();
}
}
换句话说,对于原始数组和列表,两次完全相同的方法。有什么方法可以很好地将其重构为一个方法吗?
最佳答案
您不能不应该 (*) 在单一方法中执行此操作。 Item[]
和 List<Item>
是不相关的类型。
您应该让其中一个重载调用另一个:something(Item... items)
来电something(List<Item>)
, 或 something(List<Item>)
来电something(Item... items)
.
在这两个选项中,数组重载最好调用列表重载:
public void something(Item... items) {
something(Arrays.asList(item));
}
这很便宜,因为它不复制数组,而是包装它:创建 List
是 O(1)
.
如果要从列表重载中调用数组重载:
public void something(List<Item> items) {
something(items.toArray(new Item[0]));
}
这会更贵,因为 toArray
call 必须创建并填充一个数组:它是一个 O(n)
操作,其中 n
是列表的大小。但是,它有一点优势,something
将无法替换 List
的内容,因为对数组的任何更新在执行后都会被丢弃。
(*) 你可以,但它真的很恶心,而且不是类型安全的,因为你必须接受 Object
参数,因为没有其他常见的父类(super class)型 List<Item>
和 Item[]
;你最终还是不得不重复这两种类型的循环;并且您必须处理(在运行时)传入完全不相关类型的可能性:
public void something(Object obj) {
if (obj instanceof List) {
for (Object element : (List<?>) obj) {
Item item = (Item) element; // Potential ClassCastException.
doStuff();
}
} else if (obj instanceof Item[]) {
for (Item item : (Item[]) obj) {
doStuff();
}
} else {
throw new IllegalArgumentException();
}
}
真是一团糟。感谢制造商的重载。
关于java - 如何重构这个循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41897133/