3

In a exercise, I have to create an iterator for an InputStream. The goal is that the user can do :

for(byte b : new InputStreamToIterable(myInputStream)){ //do stuff with byte } 

I finished to create it and it works well, but the Iterator method is not very elegant (lot of try/catch).

@Override public Iterator<Byte> iterator() { // TODO Auto-generated method stub try { return new Iterator<Byte>() { int data = is.read(); @Override public boolean hasNext() { // TODO Auto-generated method stub return data != -1; } @Override public Byte next() { // TODO Auto-generated method stub if(!hasNext()){ try { is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } int a = data; try { data = is.read(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return (byte)a; } @Override public void remove() { // TODO Auto-generated method stub throw new UnsupportedOperationException(); } }; } catch (IOException e) { // TODO Auto-generated catch block throw new UnsupportedOperationException(); } } 

Is there a way to make it nicer ?

2 Answers 2

2

You could clean it up somewhat by combining the two try-catch blocks in next():

boolean isClosed = false; @Override public Byte next() { if(isClosed) throw new NoSuchElementException(); int a = data; try { if(!hasNext()) { is.close(); isClosed = true; } else data = is.read(); } catch(IOException e) { throw new RuntimeException(e); } return (byte)a; } 

EDIT
Changed the code according to discussion below

Sign up to request clarification or add additional context in comments.

3 Comments

in the !hasNext() branch, a NoSuchElementException should be thrown according to docs.oracle.com/javase/6/docs/api/java/util/Iterator.html
If I close the stream, it's not compulsory to throw this exception, right ?
It should only be thrown if you try to access an element which isn't there, so basically if next() is called again after the is.close().
1

You could ...

  • in method next(): unify the two try-catch blocks into a single one
  • do the assignment int data = is.read(); in a constructor, using a try-catch-block, and so get rid of the outermost try-catch-block.

When catching the IOExceptions, instead of simply calling e.printStackTrace(); and continuing program execution, a better practice would be to enable users of this class to programmatically treat the error by re-throwing some RuntimeException (which needn't be declared and so doesn't violate the Iterable interface):

catch(IOException e) { throw new RuntimeException(e); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.