Sunil Garg
Sunil Garg

Reputation: 602

best way to Iterate over a collection and array consecutively

Its a very trivial question and related to coding Style and I am just asking to make my coding style more readable

Suppose I have a Collection like linkedList and an Array and I need to iterate over both simultaneously.
currently the best way I know is to get a iterator over list and define a index variable outside the iterator loop and increment the index variable simultaneously to access both next elements {list and array}.
Please refer the example below

LinkedList<Integer> list = new LinkedList<Integer>();
Integer[] arr = new Array[25];
// lets suppose both have 25 elements.

// My Iteration method will be 
int index =0;

for (Integer val : list) {
  System.out.println(val);
  System.out.println(arr[index++]);
}


so is it the only way or is there any other way I can perform this iteration in more readable and more relatable manner, where I don't have to take index variable separately.
I know it can be possible that array might have less or more elements than collection but I am only talking about the cases where they have equal and we need to iterate over Both of them.

PS : anybody can write a code that a computer can understand, actual challenge is to write code which humans can understand easily.

Upvotes: 0

Views: 93

Answers (3)

Andy Turner
Andy Turner

Reputation: 140318

What you have is essentially fine: it's simple, and simple can be sufficient to make code readable.

The only thing I would caution about is the side effect of index++ inside arr[index++]: if, say, you want to use the same value multiple times in the loop body, you couldn't simply copy+paste.

Consider pulling out a variable as the first thing in the loop to store the "current" array element (which is essentially what the enhanced for loop does for the list element).

for (Integer val : list) {
  Integer fromArr = arr[index++];

  // ...
}

Just to point out an alternative without having a separate variable for the index, you can use ListIterator, which provides you with the index of the element.

// Assuming list and are have same number of elements.
for (ListIterator<Integer> it = list.listIterator();
    it.hasNext();) {
  // The ordering of these statements is important, because next() changes nextIndex().
  Integer fromArr = arr[it.nextIndex()];
  Integer val = it.next();

  // ...
}

ListIterator is not an especially widely-used class, though; its use may in and of itself be confusing.


One of the downsides of the ListIterator approach is that you have to use the it correctly: you shouldn't touch it inside the loop (after getting the values), you have to put the statements in the right order, etc.

Another approach would be to create a library method analogous to Python's enumerate:

static <T> Iterable<Map.Entry<Integer, T>> enumerate(Iterable<? extends T> iterable) {
  return () -> new Iterator<T>() {
    int index = 0;
    Iterator<? extends T> delegate = iterable.iterator();

    @Override public boolean hasNext() { return delegate.hasNext(); }

    @Override public Map.Entry<Integer, T> next() {
      return new AbstractMap.SimpleEntry<>(index++, delegate.next());
    }
  };
}

This returns an iterable of map entries, where the key is the index and the value is the corresponding value.

You could then use this in an enhanced for loop:

for (Map.Entry<Integer, Integer> entry : enumerate(list)) {
  Integer fromList = entry.getValue();
  Integer fromArr = arr[entry.getKey()];
}

Upvotes: 1

winterisComing
winterisComing

Reputation: 233

I tried to simplify and handle size wise collections where both need not be of the same size. I believe this would work even if the sizes are not same and just one loop would suffice. Code snippet below:

LinkedList<Integer> list = new LinkedList<Integer>();
Integer[] arr = new Array[25];
int maxLength= Math.max(list.size(),arr.size());
//Looping over the lengthy collection( could be Linkedlist or arraylist)
for(int i=0;i<maxLength;i++){
if(list.size()>i)
  System.out.println(list[i]);
if(arr.size()>i)
  System.out.println(arr[i]);
}

Hope this helps! Thanks

Upvotes: 0

boot-and-bonnet
boot-and-bonnet

Reputation: 761

One option is to have 2 iterators, but I don't think it is any clearer:

for (Iterator<Integer> i1 = list.iterator(), i2 = Arrays.asList(arr).iterator();
    i1.hasNext() && i2.hasNext();) {
    System.out.println(i1.next());
    System.out.println(i2.next());
}

But it is more robust in that it finishes at the shorter of the 2 collections.

Upvotes: 0

Related Questions