代码之家  ›  专栏  ›  技术社区  ›  miner49r

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

  •  28
  • miner49r  · 技术社区  · 15 年前

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

    我想写些东西,比如:

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

    但是Java编译器抱怨返回。 Iterator<Object> 而不是 Iterator<Foo> . 铸造到 (Iterator<Foo>) 也不起作用。

    7 回复  |  直到 9 年前
        1
  •  58
  •   Alex B    15 年前

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

    return Collections.<Foo>emptyList().iterator();
    
        2
  •  25
  •   Thomas Stopfan    9 年前

    Java 7已经出现了很长时间了。除非您正在开发以前的Java版本,否则您将返回这样的空迭代器:

    return Collections.emptyIterator();
    
        3
  •  9
  •   Carl Manaster    15 年前

    我会沿着

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

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

    Collections.<Foo> emptyList().iterator();
    
        4
  •  4
  •   Kevin Bourrillion Gergely    15 年前

    烦恼 Collections.<Foo>emptyList().iterator() 我们提供的主要原因是 Iterators.emptyIterator() 在里面 google-collections . 在类似于您的情况下,不需要类型参数。

        5
  •  2
  •   Tom Hawtin - tackline    15 年前

    我猜这表明Java类型推理在每种情况下都不起作用,而三元运算符并不总是等价于显然等效的IF构造。

    我还想说明 避免 null . 同时避免超车 Iterator 因为他们有奇怪的庄严行为(更喜欢 Iterable )但是,假设你有正当的、非过早的理由这样做,我的首选写作方式是

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

    在我看来,如果可以推断,最好不要插入可推断的类型信息(即使它会使代码更长)。

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

    你在呼唤 iterator 这两个结果,所以不要重复你自己。

        6
  •  0
  •   miner49r    15 年前

    对不起,我知道了。您需要使用一个赋值,以便编译器能够计算出参数化类型。

    public Iterator<Foo> iterator() {
       if (underlyingData != null) {
          return underlyingData.iterator();
       } else {
          List<Foo> empty = Collections.emptyList();  // param type inference
          return empty.iterator();
       }
    }
    
        7
  •  0
  •   zagyi    12 年前
    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(){
            }
        }
    }