Java迭代器在参数化类型的空集合上

在Java中,我需要从我的方法返回一个Iterator。 我的数据来自另一个通常可以给我一个迭代器的对象,所以我可以返回它,但在某些情况下,底层数据是null。 为了保持一致性,我希望在这种情况下返回一个“空”迭代器,这样我的调用者就不必测试null。

我想写一些类似的东西:

public Iterator iterator() { if (underlyingData != null) { return underlyingData.iterator(); // works } else { return Collections.emptyList().iterator(); // compiler error } } 

但Java编译器抱怨返回的Iterator而不是Iterator 。 转换为(Iterator)也不起作用。

您可以通过以下语法获取Foo类型的空列表:

 return Collections.emptyList().iterator(); 

Java 7已经出现了很长时间。 除非您正在为以前的Java版本开发,否则您将返回一个如下所示的空迭代器:

 return Collections.emptyIterator(); 

我会更多地遵循

 public Iterator iterator() { if (underlyingData == null) return Collections. emptyList().iterator(); return underlyingData.iterator(); } 

只是,处理特殊情况并返回,然后处理正常情况。 但我的主要观点是你可以避免任务

 Collections. emptyList().iterator(); 

Collections.emptyList().iterator()的烦恼Collections.emptyList().iterator()是我们在google-collections中提供Iterators.emptyIterator()主要原因。 在像您这样的情况下,不需要类型参数。

我想这表明Java类型推断在每种情况下都不起作用,并且三元运算符并不总是等同于明显等效的if-else结构。

我还想声明避免null 。 还要避免传递Iterator ,因为它们有奇怪的有状态行为(更喜欢Iterable )。 但是,假设你有一个合理的,非过早的理由这样做,我首选的写作方式是

 public Iterator iterator() { return getUnderlyingData().iterator(); } private List getUnderlyingData() { if (underlyingData == null) { return Collections.emptyList(); } else { return underlyingData; } } 

IMO,如果可以推断出它,最好不要插入可推断类型信息(即使它使你的代码更长)。

您几乎肯定会多次执行此操作,因此请插入getUnderlyingData方法,而不是仅声明局部变量。

你在两个结果上调用iterator ,所以不要重复自己。

对不起,我明白了。 您需要使用赋值,以便编译器可以找出参数化类型。

 public Iterator iterator() { if (underlyingData != null) { return underlyingData.iterator(); } else { List empty = Collections.emptyList(); // param type inference return empty.iterator(); } } 
 public final class EmptyIterator{ public static Iterator iterator(){ return new Empty(); } private static class Empty implements Iterator { public boolean hasNext(){ return false; } public Object next(){ throw new NoSuchElementException(); } public void remove(){ } } }