Ways to Iterate Over a List in Java

Ways to iterate over a list in Java

The three forms of looping are nearly identical. The enhanced for loop:

for (E element : list) {
. . .
}

is, according to the Java Language Specification, identical in effect to the explicit use of an iterator with a traditional for loop. In the third case, you can only modify the list contents by removing the current element and, then, only if you do it through the remove method of the iterator itself. With index-based iteration, you are free to modify the list in any way. However, adding or removing elements that come before the current index risks having your loop skipping elements or processing the same element multiple times; you need to adjust the loop index properly when you make such changes.

In all cases, element is a reference to the actual list element. None of the iteration methods makes a copy of anything in the list. Changes to the internal state of element will always be seen in the internal state of the corresponding element on the list.

Essentially, there are only two ways to iterate over a list: by using an index or by using an iterator. The enhanced for loop is just a syntactic shortcut introduced in Java 5 to avoid the tedium of explicitly defining an iterator. For both styles, you can come up with essentially trivial variations using for, while or do while blocks, but they all boil down to the same thing (or, rather, two things).

EDIT: As @iX3 points out in a comment, you can use a ListIterator to set the current element of a list as you are iterating. You would need to use List#listIterator() instead of List#iterator() to initialize the loop variable (which, obviously, would have to be declared a ListIterator rather than an Iterator).

What is the best way to iterate over list

Calling size() at each iteration is not really a problem. This operation is O(1) for all the collections I know of: size() simply returns the value of a field of the list, holding its size.

The main problem of the first way is the repeated call to get(i). This operation is O(1) for an ArrayList, but is O(n) for a LinkedList, making the whole iteration O(n2) instead of O(n): get(i) forces the list to start from the first element of the list (or the last one), and to go to the next node until the ith element.

Using an iterator, or using a foreach loop (which internally uses an iterator), guarantees that the most appropriate way of iterating is used, because the iterator knows about how the list is implemented and how best go from one element to the next.

BTW, this is also the only way to iterate through non-indexed collections, like Sets. So you'd better get used to use that kind of loop.

Iterate by two elements on a list with Java

To achieve the task it's more then enough to use a regular loop and return on each step [curent,curent+1] list elements.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class TestList
{
public static void main(String args[])
{
ArrayList <String> l = new ArrayList(Arrays.asList("a","b","c","d"));
List al = new TestList().iterateList(l);
al.forEach(System.out::println);

}
public List iterateList(List l)
{

ArrayList<String> al = new ArrayList();
if(l==null || l.size() <= 1)
{
//list size should be not_null and greater then 1 : 2_fine
return null;
}
for(int i=0;i<l.size()-1;i++)
{
String element = l.get(i)+","+l.get(i+1);
al.add(element);
}
return al;
}

Output:

a,b

b,c

c,d

How to iterate through list of lists on demand?

The following generic lazy function to calculate all combinations do the job and works for any number of lists or any other structure

static Stream<int []> combinationsStream(final int... numElems) {
final int numCombinations = Arrays.stream(numElems) // the number of solutions is
.map(n -> n + 1) // possibles sizes
.reduce(1, (a, b) -> a * b); // product

final int[] queue = Arrays.stream(numElems).map(i -> -1).toArray(); // for every item take n elements
final int[] i = new int[]{0}; // volatile (final) integer
final Function<int [], int []> next = o -> { // compute the next combination
while (true) {
if (i[0] == numElems.length) { // if is the last position
i[0] -= 1; // we will back
return queue; // but it's a combination
}
queue[i[0]] += 1; // take one more of i[0]-th element
if (queue[i[0]] > numElems[i[0]]) // if no more of this
queue[i[0]--] = -1; // reset and go back
else
i[0] += 1; // if not, go forward
}
};
return Stream.iterate(null, next::apply) // iterate getting next over and over
.skip(1) // avoid the seed (null)
.limit(numCombinations); // limit the stream to combs number
}

since only work with indexes, you can use as follows

Let your list:

// let you list of list (from somewhere)
List<List<String>> iterators = asList(
asList("1", "2"),
asList("4", "5"),
asList("7", "8")
);

(lists could contains different number of elements)

then, to get a lazy stream with all combinations simply convert the list of list to an array of max indexes

// we get combinations in a lazy way simply with
// (you could set this stream in your private class field if you wish)
Stream<int []> lazyCombinations = combinationsStream(iterators.stream()
.mapToInt(g -> g.size() - 1).toArray());

in your case the call will be combinationsStream(1, 1, 1) since valid indexes are 0, 1 for each list.

To convert some index combination to your String output get the indexes and join

// to convert the indexes array to values (and concatenate all) you can write the function
Function<int [], String> toString = indexes -> IntStream
// for each list
.range(0, indexes.length)
// get the indexes[i]-th element
.mapToObj(i -> iterators.get(i).get(indexes[i]))
// and join
.collect(joining());

then, simply map the previous Stream<int []> to Stream<String> using that function

// now you can convert your indexes stream to your final combinations stream (all lazy)
Stream<String> lazySolutions = lazyCombinations.map(toString);

you can use the Stream in many ways (i.e. return in a Web Service lazily) but, if you wish take one by one you can convert to an iterator.

The itarator is lazy too

// if you need peek combinations on demand (not in a streaming way) convert stream to iterator
Iterator<String> lazyIterator = lazySolutions.iterator();

Then, you can take only one

// you can take one by one (e.g. inside a `getNextCombination`)
System.out.println("Only one: " + lazyIterator.next());

or as many as you consider

// or to the end
lazyIterator.forEachRemaining(System.out::println);

with output

Only one: 147
148
157
158
247
248
257
258

How to iterate over a List containing array of strings

If a way to solve it is not important for you, I suggest using foreach statements:

for(String[] a : myEntries)
for(String s : a)
// do what you want to

Otherwise, you should write like

Iterator<String[]> iterator = myEntries.iterator();
while(itr.hasNext())
for(String temp : itr.next())
// Don't worry, itr.next() will be created only one time
// for an each iteration (while)
System.out.println(temp);

, that looks not pretty and may have difficulty in reading.

Efficient way to iterate over two related ArrayLists?

The Answer by dreamcrash is correct: While your looping of a pair of arrays works, you should instead take advantage of Java as a OOP language by defining your own class.

Record

Defining such a class is even simpler in Java 16 with the new records feature. Write your class as a record when it’s main purpose is communicating data, transparently and immutably.

A record is very brief by default. The compiler implicitly creates the constructor, getters, equals & hashCode, and toString. You need only declare the type and name of each member field.

record ColorNoun ( String color , String noun ) {}

Use a record like a conventional class. Instantiate with new.

ColorNoun blueSky = new ColorNoun ( "Blue" , "Sky" ) ;

Note that a record can be declared locally within a method, or declared separately like a conventional class.

Iterate over a list of lists and check for a condition using java 8

Use flatMap to combine all the players’ positions into a single Stream:

public boolean testAllPositionsAreCovered(Team team,
String[] positions) {

Set<String> positionsOfTeams = team.getPlayers().stream()
.flatMap(p -> p.getPositions().stream())
.map(Position::getPosition)
.collect(Collectors.toSet());
return positionsOfTeams.containsAll(Arrays.asList(positions));
}


Related Topics



Leave a reply



Submit