1

I am going to have a class that has a ArrayList people field I want clients of this class to be able to iterate over those objects. How do I do this? Do I just return people.iterator(); ?

for example, in the client I want to be able to do this:

for( Person p : people ) {
    // do something
}

Is this what I need in my class?

public class People  implements Iterable<Person> {

private ArrayList<Person> people;

@Override
public Iterator<Person> iterator() {
    // TODO Auto-generated method stub
    return people.iterator();
}
2
  • "Is this what I need in my class?" ... Erm, we don't know, is it? That will certainly return an Iterator from the private ArrayList. Commented Aug 15, 2013 at 1:24
  • Can who ever down voted my question, please let me know why? I certainly don't intend on asking dumb questions. I think from the answers below, I now understand a bit more about the implications of the above code in my question, but I am not sure what other research I should have done or what what was unclear or not useful. Commented Sep 1, 2013 at 3:42

3 Answers 3

2

If you want to prevent modification to the list itself via the iterator, just delegate iterator() to an unmodifiable list like this:

public class People implements Iterable<Person> {

    private ArrayList<Person> people;

    @Override
    public Iterator<Person> iterator() {
        return Collections.unmodifiableList(people).iterator();
    }

}

Otherwise, what you have is fine.

Note, however, that unless Person is immutable, there is nothing you can do to prevent a caller from modifying the Person objects themselves. If that's OK, then no big deal. If that's a problem, then you could create a deep copy of people and return an iterator to that.

If you want the returned iterator to reflect modifications to the Persons but not to allow changing of the Persons, or if a deep copy is too expensive or unnecessary, you could create an ImmutablePerson that extends Person and wraps a Person but does not allow modification via setters, and return a list of those wrapped around the actual Person objects.

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

1 Comment

Thanks Jason , you helped me again. Looking at the places in my client code that loop thru the persons in people, this is exactly the functionality I wanted to push down into the class in the first place.
1

Yes. The enhanced for loop requires an array or Iterable. Iterable is required to have iterator( that returns a reasonable iterator that has useful meaning in regard to your data.

You can now use the enhanced for loop and it is somewhat semantically correct. However, Iterator provides remove( so anyone using your iterator can remove things from your people list, which may not be what you want. Perhaps using new ArrayList(people).iterator() or Collctions.unmodifiableList(people).iterator() can work as you copy the list and get the iterator for it.

You can also provide getPeople by creating a getter that creates an ImmutableList or just a copy of your internal arrayList.

On another note, why not extend ArrayList if you need extra functionality? I haven't seen exactly what you're doing with it so I can only guess.

3 Comments

extending ArrayList<Person> was my original plan, but I then I thought encapsulating might be better. The other reason , is because I need this to be Parcelable, and I could not figure out how to make an extension of ArrayList<Person> to be Parcelable (Person already is and I think I can figure out how to make the class with the ArrayList<Person> field Parcelable
@nPn OK. Remember that this can provide loss of control in terms of data protection due to the iterator's remove( method.
@hexafraction You could return Collections.unmodifiableList(people).iterator() (see my answer below).
0

Simply provide a getter for your People list:

public ArrayList<Person> get getPeople() {
   return people;
}

5 Comments

Returning a reference to the internal list may not be a good idea, perhaps a copy can be used instead?
@hexafraction why returning a reference o a list is not a good idea? it is not a static list.
We don't know for sure but the class the OP wrote could use it internally in places we can't see, as the code looks abridged.
At the bare minimum I would return Collections.unmodifiableList(people);, and only if a Person was immutable (and maybe go one step further and say only if people was final, depending on requirements).
I think I just have a lot to learn. I think the answer is not to iterate outside the class? I should provide the the class with a method to do what I want inside the class, right?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.