Java iterator over an empty collection of a parameterized type

后端 未结 7 1487
隐瞒了意图╮
隐瞒了意图╮ 2021-01-03 18:36

In Java, I need to return an Iterator from my method. My data comes from another object which usually can give me an iterator so I can just return that, but in some circums

相关标签:
7条回答
  • 2021-01-03 18:57

    Java 7 has been out for a long time now. Unless you're developing for a previous Java version, you would return an empty iterator like this:

    return Collections.emptyIterator();
    
    0 讨论(0)
  • 2021-01-03 19:03

    Sorry, I figured it out. You need to use an assignment so that the compiler can figure out the parameterized type.

    public Iterator<Foo> iterator() {
       if (underlyingData != null) {
          return underlyingData.iterator();
       } else {
          List<Foo> empty = Collections.emptyList();  // param type inference
          return empty.iterator();
       }
    }
    
    0 讨论(0)
  • 2021-01-03 19:08
    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(){
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-03 19:09

    I guess this shows that Java type inference doesn't work in every case and that the ternary operator is not always equivalent to the apparently equivalent if-else construct.

    I also want to state avoid null. Also avoid passing Iterators about, because they have strange stateful behaviour (prefer Iterable). However, assuming you have a legitimate, non-premature reason for doing this, my preferred way of writing it would be

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

    IMO, it's better not to insert the inferable type information if it can be inferred (even if it makes your code longer).

    You are almost certainly going to do it more than once, so insert a getUnderlyingData method instead of just declaring a local variable.

    You are calling iterator on both results, so do not repeat yourself.

    0 讨论(0)
  • 2021-01-03 19:15

    I'd go more along the lines of

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

    Just, handle the special case and return, then handle the normal case. But my main point is that you can avoid the assignment with

    Collections.<Foo> emptyList().iterator();
    
    0 讨论(0)
  • 2021-01-03 19:17

    The annoyance of Collections.<Foo>emptyList().iterator() is the main reason we provide Iterators.emptyIterator() in google-collections. No type parameter needed, in cases like yours.

    0 讨论(0)
提交回复
热议问题