java - iterating a linked list - java

if I use a for-each loop on a linked list in java,
is it guaranteed that I will iterate on the elements in the order
in which they appear in the list?

I found 5 main ways to iterate over a Linked List in Java (including the Java 8 way):
For Loop
Enhanced For Loop
While Loop
Iterator
Collections’s stream() util (Java8)
For loop
LinkedList<String> linkedList = new LinkedList<>();
System.out.println("==> For Loop Example.");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
Enhanced for loop
for (String temp : linkedList) {
System.out.println(temp);
}
While loop
int i = 0;
while (i < linkedList.size()) {
System.out.println(linkedList.get(i));
i++;
}
Iterator
Iterator<String> iterator = linkedList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
collection stream() util (Java 8)
linkedList.forEach((temp) -> {
System.out.println(temp);
});
One thing should be pointed out is that the running time of For Loop or While Loop is O(n square) because get(i) operation takes O(n) time(see this for details). The other 3 ways take linear time and performs better.

Linked list is guaranteed to act in sequential order.
From the documentation
An ordered collection (also known as a
sequence). The user of this interface
has precise control over where in the
list each element is inserted. The
user can access elements by their
integer index (position in the list),
and search for elements in the list.
iterator()
Returns an iterator over the elements in this list in proper sequence.

As the definition of Linkedlist says, it is a sequence and you are guaranteed to get the elements in order.
eg:
import java.util.LinkedList;
public class ForEachDemonstrater {
public static void main(String args[]) {
LinkedList<Character> pl = new LinkedList<Character>();
pl.add('j');
pl.add('a');
pl.add('v');
pl.add('a');
for (char s : pl)
System.out.print(s+"->");
}
}

Linked list does guarantee sequential order.
Don't use linkedList.get(i), especially inside a sequential loop since it defeats the purpose of having a linked list and will be inefficient code.
Use ListIterator
ListIterator<Object> iterator = myLinkedList.listIterator();
while( iterator.hasNext()) {
System.out.println(iterator.next());
}

Each java.util.List implementation is required to preserve the order so either you are using ArrayList, LinkedList, Vector, etc. each of them are ordered collections and each of them preserve the order of insertion (see http://download.oracle.com/javase/1.4.2/docs/api/java/util/List.html)

Adding my inputs for future visitors.
First things first: as per $jls-14.14.2, for-each internally use Iterator.
Now, when you iterate over LinkedList using a for-each or an iterator then the looping is always sequential.
But this is prone to thread safety issues. So, two things can happen:
If you use a non-threadsafe List implementation then you will run into ConcurrentModificationException
You can use a threadsafe List implementation like CopyOnWriteArrayList. And if you must use a LinkedList only then use Collections.synchronizedList() to convert your non-threadsafe LL into a threadsafe LL, but again you need to watch out for using iterator in a threadsafe manner.

Related

Java Iterator infinite loop iterates only the 1st item in hashmap

I am executing a database query, and as result I get a HashMap. I want to iterate through all the results, but I infinitely add the first item from the result to the arraylist.
QueryResult result=engine.query(query,params);
while(result.iterator().hasNext()) {
HashMap res= (HashMap)result.iterator().next();
Node node=(Node)res.get("n");
results.add(new BusyProfile(node));
}
How to iterate through each object and why do I have infinite loop? Thanks!
Everytime you call result.iterator(), a new Iterator is created, pointing to the first item.
So create it before your loop:
Iterator<?> it = result.iterator();
while (it.hasNext()) {
HashMap res = (HashMap)it.next();
//...
}
You are overwriting your iterator! When result.iterator() is called, you create your iterator but on each iteration, it's creating a new one and it continues to point to the beginning - causing the infinite loop.
What you need to do in this case is save the iterator and then use it to move through the collection.
QueryResult result = engine.query(query,params);
//Save iterator
Iterator i = result.iterator();
while(i.hasNext()) {
HashMap res = (HashMap)i.next();
Node node = (Node)res.get("n");
results.add(new BusyProfile(node));
}
Before you can access a collection through an iterator, you must
obtain one. Each of the collection classes provides an iterator( )
method that returns an iterator to the start of the collection. By
using this iterator object, you can access each element in the
collection, one element at a time.
In general, to use an iterator to cycle through the contents of a
collection, follow these steps −
Obtain an iterator to the start of the collection by calling the
collection's iterator( ) method.
Set up a loop that makes a call to hasNext( ). Have the loop iterate
as long as hasNext( ) returns true.
Within the loop, obtain each element by calling next( ).
There is a quick tutorial here:
https://www.tutorialspoint.com/java/java_using_iterator.htm
All answers posted before mine explained that result.iterator() will instantiate a new iterator each time it is invoked.
And it makes not sense to create an iterator during each iteration for the same iterator that you are iterating with : while(result.iterator().hasNext()) {
.It is right.
Beyond this misuse of the Iterator, you should read the javadoc of the class you are using. It may often help you to create a more effective code.
According to the javadoc of org.neo4j.ogm.session.result.QueryResult, the
QueryResultclass implements the Iterable interface in this way Iterable<Map<String,Object>>.
So instead of doing thing more complicated than required, just use an enhanced for.
It would produce a shorter and more readable code.
Besides, using the more restricted scope for a variable is better as it prevents to use it unsuitably.
With the enhanced for, you don't need any longer to declare the iterator before the loop.
It will be used in the compiled class (as enhanced for uses under the hood an iterator) but it will be restricted to the scope of the loop.
So you should really consider this way :
QueryResult result = engine.query(query,params);
for (Map<String,Object> currentMap : result) {
Node node = (Node) currentMap.get("n");
results.add(new BusyProfile(node));
}
You should call the iterator() method once and then store (and use) the returned value.
Reuse the Iterator
Iterator i = result.iterator();
if(i.hasNext()) {
HashMap res= (HashMap)i.next();
Node node=(Node)res.get("n");
results.add(new BusyProfile(node));
}

Why Looping through ArrayList<String> is same as a regular array? [duplicate]

This question already has answers here:
How does the Java 'for each' loop work?
(29 answers)
Closed 9 years ago.
Method 1
ArrayList<String> list = new ArrayList<String>();
for (String s : list) {
write.append(s);
write.append('\n');
}
How is looping through an ArrayList this way possible? isn't this method only applicable for static usual arrays, for example : String[] list2 = new String[]{"1","2","3","4"}; ?
If I want to loop over the ArrayList<String> list, why not doing this for example:
Method 2
for (int i = 0; i < list.size(); i++) {
write.append(list.get(i));
write.append("\n");
}
I'm just not understanding how is it possible to use Method 1. Any explanation is welcomed.
ArrayList implements Iterable which makes it provide an Iterator object, which is then user by for loop.
Any class implementing Iterable would be usable in a for loop, just like an array.
The simplified for loop is made to look same for arrays and collections, but under the hood, it uses index for arrays and iterator for collections.
These are called for-each loops, and can be applied to both arrays and collections. Format:
for ([type] [var-name] : [array or iterable value]) {
...
}
To use a for-each loop, you only need to satisfy one of two conditions:
The iteration value is an array, or
the iteration value is an Iterable.
The biggest reason we do this is because List isn't the only Iterable that we can use in the loop, but it is the only one that can be indexed. This allows you to do generic iteration instead of locking yourself into a fixed, indexed list format.
For example, HashSet is not ordered, but I can still iterate over it in a for-each loop:
HashSet<String> strs = new HashSet<String>();
for (String str : strs) { ... }
I can also have a method take an Iterable instead of a List:
public static void printStrings(Iterable<String> strs) {
for (String str : strs) {
System.out.println(str);
}
}
There is no way for me to iterate over it using an index without first copying it into something else, like an array or a List.
Another important reason to use the for-each loop is that it compiles to using the Iterator off the list (via Iterable.iterator()), which allows for fail-fast iteration. This results in things like ConcurrentModificationExceptions to tell us that the collection was modified while we were iterating over it. For example, this will always throw a ConcurrentModificationException:
List<String> strs = ... ;
for (String str : strs) {
strs.remove(str);
}
But this won't:
List<String> strs = ... ;
for (int i = 0; i < strs.length(); i++) {
strs.remove(str);
}
This is good for multi-threaded applications because you're supposed to lock the list before you access it since most List implementations aren't designed for thread-safety, and iteration is never thread-safe without external synchronization, both with indexing and with Iterator. If one thread is iterating over it while another changes it, this can (not guaranteed, but can) throw a ConcurrentModificationException, which tells you that the list isn't properly locked. The indexed for could never give you this kind of information. Instead, it will just exhibit strange behavior like skipping elements.
There is an interface called Iterable which allows fast iteration. If something implements Iterable, fast iteration is allowed. The Iterable interface has one method, which returns an Iterator which can be used to iterate the elements.
The first is called an enhanced-for, or "for each". It is considered syntactic sugar for the traditional model of for statements - allowing you to iterate over every element in a collection - be that an array or anything in the Java Collections Framework.
There are two distinct differences between these types of loops:
The enhanced for statement indexes the value for you, storing it in the temporary variable as part of the declaration. Thus, you don't have to do things like val[i] or value.get(i) - this happens for you automatically.
You don't get to specify what you increment by in the enhanced for statement; you either iterate over all elements in the collection, or you terminate early via a break statement.
The reason that this can be iterated over using a standard array is defined in the JLS, specifically §14.14.2 - since an array doesn't implement Iterable, it converts it to a standard-behaving for statement.
...Otherwise, the Expression necessarily has an array type, T[].
Let L1 ... Lm be the (possibly empty) sequence of labels immediately preceding the enhanced for statement.
The enhanced for statement is equivalent to a basic for statement of the form:
T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
VariableModifiers(opt) TargetType Identifier = #a[#i];
Statement
}
#a and #i are automatically generated identifiers that are distinct from any other identifiers (automatically generated or otherwise) that are in scope at the point where the enhanced for statement occurs.
This is the for-each syntax: http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
The compiler will convert your code in method 1 to something like:
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String s = iterator.next();
write.append(s);
write.append('\n');
}

How to list elements maintaining order and reverse iteration?

What is the best list/set/array in Java that combines the following aspects:
maintain order of added elements
make if possible to both iterate forwards and backwards
of course good performance
I thought about a LinkedList, I then could insert elements by add(0, element) which would simulate a reverse order. Most of the time I will be using backwards iteration, so using this I can just iterate trough.
And if not, I can list.listIterator().hasPrevious().
But are there better approaches?
ArrayList will probably be your best bet. You can iterate through it in the following manner:
for (ListIterator it = list.listIterator(list.size()); it.hasPrevious();) {
Object value = it.previous();
}
A LinkedList will work but it will have more object creation overhead since you need to instantiate a Link for each element you store.
If you can get by index and wish to iterate over the collection then you can use a List and get(index) allow you to get the object in that place in the list. Arrays allow you to do this, you can just reference the index as normal, however if your array might grow then a Collection is going to be easier to use.
You can use List.size() and element through the object using a for loop rather than using an Iterator object, this will allow you to iterator over the list both forwards and backwards. For example:
List<AnObject> myList = new ArrayList<AnObject>;
// Add things to the list
for (int i = 0 ; i < myList.size; i++) {
AnObject myObject = myList.get(i);
}
for (int i = myList.size()-1 ; i <= 0 ; i--) {
AnObject myObject = myList.get(i);
}
Set is not applicable as a Set does not maintain ordering.

Performance difference between Iterator Class and foreach construct

I have the following code running, but I sometimes get some sort of concurrency exception when running it.
ArrayList<Mob> carriers = new ArrayList<Mob>();
ArrayList<Mob> mobs = new ArrayList<Mob>();
...
for (Mob carrier : carriers){
for (Mob mob : mobs){
checkInfections (carrier, mob);
}
}
I refactored it to solve the concurrency problem, but it did lead me to a question. Would there be a difference in performance if I change the for construct to an Iterator pattern? What's the access level difference between the foreach construct and the Iterator class?
The difference is largely syntactic sugar except that an Iterator can remove items from the Collection it is iterating. Technically, enhanced for loops allow you to loop over anything that's Iterable, which at a minimum includes both Collections and arrays.
Don't worry about performance differences. Such micro-optimization is an irrelevant distraction. If you need to remove items as you go, use an Iterator. Otherwise for loops tend to be used more just because they're more readable ie:
for (String s : stringList) { ... }
vs:
for (Iterator<String> iter = stringList.iterator(); iter.hasNext(); ) {
String s = iter.next();
...
}
Behind the scenes the new style for is implemented in terms of iterators by the compiler, so there will be no difference if you do that yourself.
The "some sort of concurrency exception" you're talking about is most likely java.util.ConcurrentModificationException. You get this because you cannot change the list while you are iterating over it; if you do that, the iterator will notice and throw this exception.
If you need to remove elements from a list while iterating over it, then do it through the remove() method on the iterator, for example:
List<String> list = ...; // wherever you get this
for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
String s = iter.next();
if (...) {
iter.remove(); // Remove element through iterator
}
}
(Note: You can't use the foreach syntax for the loop in this case, because you need explicit access to the iterator).
You can use Iterator(interface) only on collections like List, Set & Queue but for each loop cab be used for everything which is iterable like Collections and Array. And for each loop is more readable..

Best way to get value from Collection by index

What is the best way to get value from java.util.Collection by index?
You shouldn't. a Collection avoids talking about indexes specifically because it might not make sense for the specific collection. For example, a List implies some form of ordering, but a Set does not.
Collection<String> myCollection = new HashSet<String>();
myCollection.add("Hello");
myCollection.add("World");
for (String elem : myCollection) {
System.out.println("elem = " + elem);
}
System.out.println("myCollection.toArray()[0] = " + myCollection.toArray()[0]);
gives me:
elem = World
elem = Hello
myCollection.toArray()[0] = World
whilst:
myCollection = new ArrayList<String>();
myCollection.add("Hello");
myCollection.add("World");
for (String elem : myCollection) {
System.out.println("elem = " + elem);
}
System.out.println("myCollection.toArray()[0] = " + myCollection.toArray()[0]);
gives me:
elem = Hello
elem = World
myCollection.toArray()[0] = Hello
Why do you want to do this? Could you not just iterate over the collection?
I agree with Matthew Flaschen's answer and just wanted to show examples of the options for the case you cannot switch to List (because a library returns you a Collection):
List list = new ArrayList(theCollection);
list.get(5);
Or
Object[] list2 = theCollection.toArray();
doSomethingWith(list[2]);
If you know what generics is I can provide samples for that too.
Edit: It's another question what the intent and semantics of the original collection is.
In general, there is no good way, as Collections are not guaranteed to have fixed indices. Yes, you can iterate through them, which is how toArray (and other functions) work. But the iteration order isn't necessarily fixed, and if you're trying to index into a general Collection, you're probably doing something wrong. It would make more sense to index into a List.
I agree that this is generally a bad idea. However, Commons Collections had a nice routine for getting the value by index if you really need to:
CollectionUtils.get(collection, index)
You must either wrap your collection in a list (new ArrayList(c)) or use c.toArray() since Collections have no notion of "index" or "order".
Convert the collection into an array by using function
Object[] toArray(Object[] a)
It would be just as convenient to simply convert your collection into a list whenever it updates. But if you are initializing, this will suffice:
for(String i : collectionlist){
arraylist.add(i);
whateverIntID = arraylist.indexOf(i);
}
Be open-minded.
you definitively want a List:
The List interface provides four methods for positional (indexed) access to list elements.
Lists (like Java arrays) are zero based.
Also
Note that these operations may execute in time proportional to the index value for some
implementations (the LinkedList class, for example). Thus, iterating over the elements in a > list is typically preferable to indexing through it if the caller does not know the
implementation.
If you need the index in order to modify your collection you should note that List provides a special ListIterator that allow you to get the index:
List<String> names = Arrays.asList("Davide", "Francesco", "Angelocola");
ListIterator<String> i = names.listIterator();
while (i.hasNext()) {
System.out.format("[%d] %s\n", i.nextIndex(), i.next());
}
use for each loop...
ArrayList<Character> al = new ArrayList<>();
String input="hello";
for (int i = 0; i < input.length(); i++){
al.add(input.charAt(i));
}
for (Character ch : al) {
System.Out.println(ch);
}
If your Collection is a List, simply cast it as a List and call get(final int index). Otherwise, it might make sense to consider finding the nth element in an ordered set, for example if it's a LinkedHashSet respecting insertion order (keep in mind that it's possible to create such an instance not respecting insertion order), you can use Collection.stream().skip(index).limit(1).findFirst().orElse(null).
You can get the value from collection using for-each loop or using iterator interface. For a Collection c
for (<ElementType> elem: c)
System.out.println(elem);
or Using Iterator Interface
Iterator it = c.iterator();
while (it.hasNext())
System.out.println(it.next());

Categories

Resources