foreach语法中的三元运算符

时间:2017-03-12 12:33:20

标签: java collections foreach ternary-operator

我有两个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不适用于对象类型。

为什么?

2 个答案:

答案 0 :(得分:5)

当你在三元组中使用两个表达式作为两个选择时,Java需要决定它们的常见类型,以便决定表达式的类型。

由于columnsString[]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,因此它成为三元表达式的最终类型。