我有两个String
个集合:String... columns
- 这只是一个简单的数组,而来自地图的KeySet<String>
。
for(String it : columns) // works
for(String it : FIELDS.keySet()) // works
for(String it : ((columns.length > 0) ? columns : FIELDS.keySet())) // doesn't.
Foreach不适用于对象类型。
为什么?
答案 0 :(得分:5)
当你在三元组中使用两个表达式作为两个选择时,Java需要决定它们的常见类型,以便决定表达式的类型。
由于columns
为String[]
,FIELDS.keySet()
为Set<String>
,因此最常见的类型为java.lang.Object
。每种类型都支持迭代,但公共基类型不支持迭代。这就是你收到错误的原因。
您可以将columns
转换为Set<String>
,或将FIELDS.keySet()
转换为String[]
来解决此问题:
Set<String> keySet = FIELDS.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()])
for(String it : ((columns.length > 0) ? columns : keyArray)) {
...
}
(来自评论)在我的案例中,转换不值得。简单
if for(x) else for(y)
更适合它,因为它是单行循环,比副本消耗更少。
此更高效的另一个原因是Java编译器能够生成更高效的代码。由T.J. Crowder注明in his comment,
[Java]编译器必须为它们发出不同的代码,具体取决于它是处理数组还是
Iterable
使用两个foreach
的方法可让编译器选择一个更适合集合类型的增强循环,而不是将两个集合强制转换为相同类型的对象。
答案 1 :(得分:2)
这是因为三元运算符的两个部分必须共享相同的公共类型,以便它们有资格获得for-each结构。 for-each构造需要Object[]
或Iterable
。
在您的情况下,一个是array
,另一个是Set
。这两种类型最接近的共同父项是Object
,因此它成为三元表达式的最终类型。