问题描述
我有一个应用程序,我将原始数组和列表用于一个名为 Item 的类.出于遗留原因,这些可以互换使用(我也希望这只是一种类型,但它就是这样).
I've got an application where I use primitive arrays and Lists for a class called Item. These are used interchangeably for legacy reasons (I also wish this was just one type, but it's the way it is).
现在我必须添加一个像这样通过 for-each 循环工作的新方法:
Now I have to add a new method like this that works via a for-each loop:
public void something(Item... items) {
for (Item i : items) {
doStuff();
}
}
public void something(List<Item> items) {
for (Item i : items) {
doStuff();
}
}
换句话说,对于原始数组和列表,两次完全相同的方法.有什么方法可以很好地将其重构为单个方法吗?
In other words, exactly the same method twice for both primitive Arrays and Lists. Is there any way to nicely refactor this into a single method?
推荐答案
您不应该 (*) 在单个方法中执行此操作.Item[]
和 List
是不相关的类型.
You shouldn't (*) do this in a single method. Item[]
and List<Item>
are unrelated types.
您应该让一个重载调用另一个:something(Item... items)
调用 something(List)
或 something(List)
调用 something(Item... items)
.
You should make one of the overloads call the other: either something(Item... items)
calls something(List<Item>)
, or something(List<Item>)
calls something(Item... items)
.
两个选项中,数组重载最好调用列表重载:
Of the two options, it is better for the array overload to call the list overload:
public void something(Item... items) {
something(Arrays.asList(item));
}
这很便宜,因为它不复制数组,而是包装它:创建List
是O(1)
.
This is cheap, because it doesn't copy the array, but rather wraps it: creating the List
is O(1)
.
如果您要从列表重载中调用数组重载:
If you were to invoke the array overload from the list overload:
public void something(List<Item> items) {
something(items.toArray(new Item[0]));
}
这会更昂贵,因为 toArray
调用必须创建和填充数组:这是一个 O(n)
操作,其中 n
是列表的大小.但是,它有一个轻微的优势,即 something
将无法替换 List
的内容,因为对数组的任何更新都会在执行后简单地丢弃.
This would be more expensive, since the toArray
call has to create and populate an array: it is an O(n)
operation, where n
is the size of the list. However, it has the slight advantage that something
would not be able to replace the contents of the List
, since any updates to the array are simply discarded after execution.
(*) 你可以,但这真的很糟糕,而且不是类型安全的,因为你必须接受一个 Object
参数,因为有没有其他常见的 List
和 Item[]
超类型;并且你最终还是不得不为这两种类型重复循环;并且您必须处理传入(在运行时)完全不相关的类型的可能性:
(*) You can, but it would be really gross, and not type-safe, as you'd have to accept an Object
parameter, as there is no other common super type of List<Item>
and Item[]
; and you'd still end up having to repeat the loops for the two types; and you'd have to handle the possibility of a completely unrelated type being passed in (at runtime):
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();
}
}
真是一团糟.感谢制造商的重载.
What a mess. Thank the maker for overloads.
这篇关于我如何重构这个循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!