Arraylists without loop - java

I am learning Java and I am wondering one thing:
Do I need for-loops for arraylist, before one can consider it as arraylist? Because every example I find, shows me some sort of a loop.
So will you consider this as arraylist?
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("Item");
And then use the elements from the list in methods etc.
Or is this better(even if the first example is good enough for you):
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("Item");
for (int i = 0; i < stringList.size(); i++)
String item = stringList.get(i);
System.out.println("Item " + i + " : " + item);
}

No, you do not have to use loops when using collections. There's nothing wrong with not using loops. Although, in almost every situation where you're going to use some sort of collection, you're going to want to be using some sort of a loop.
One exception I might see where you need to use a collection and definitely won't loop with it is if you're using a method that takes a collection as an argument and you can't override, but you want to perform whatever operation on a single object.
In this case, you could load an ArrayList with a single string so that that single string could be sent to the method via the collection.
Also, in both Android and iOS programming, you will frequently see some sort of collection used in order to save user settings, and these aren't necessarily used in loops.

Just because a list has only 1 element doesn't mean it is no longer a list. Loops are found with all collections because iterating through a list is usually the reason you needed a list in the first place. If you know your list only has 1 item then you don't ever need a loop, you can just System.out.println(stringList.get(0)).

You absolutely do not need to use loop control structures when dealing with collections. Often you can write cleaner collection-manipulating code using a library like Guava.

Related

Which approach is more expensive to restrict an ArrayList to have only DISTINCT entries?

I have contacts that are being added to an arraylist, now some contacts are common in other applications so duplicate entries are also saved in that.
I'm aware of two approaches to resolve this situation, I'm not sure which approach should I follow ?
first:
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
ArrayList<String> temp = new ArrayList<String>();
temp.add(name);
if (!contactList.contains(name)) {
contactList.add(name);}
second:
Adding it to hashset as it doesn't allow duplicate entries and then adding it back to arraylist-
String name = getStrin(...);
contactList.add(name);
// after the loop has completed adding all elements
HashSet hs = new HashSet();
hs.addAll(contactList);
contactList.clear();
contactList.addAll(hs);
You should follow the second way, as it is better, and optimized for distinct values.
EVen when you add it to a HashSet, the HashSet will perform operations to check if entry exists and will have to reorganize itself to accommodate the new entry albeit in a more optimized way. So I don't think there is any major advantage to be gained by going for the second method. Plus you are doing addAll() and clear() operations in method 2, so any optimization gained by HashSet usage might be offset by these.
I suggest you go for first method itself, But you should test both methods and measure whichever is better for your specific test cases and application requirements.

Equivalence of for loop to List.get in java

I have an List with one element in it, but which may have more later. The list I am using is an ArrayList. I find that by calling List.get(0) instead of using a for loop I get faster results. Why is this? Shouldn't looping over 1 item be the same as getting 1 item? If not then how can I get similar performance? I know that my array will eventually be larger than one item. I am using this loop in the body of a opengl renderer. When I use the loop my fps drops by 45.
Edit: I have fixed the problem. My renderer was adding a new value to the list each time it was rendered.
Using the enhanced for loop (for-each) in Java results in compiled code that works like this:
Iterator<Thing> it = list.iterator();
while(it.hasNext()) {
yourLoop.loopBody(it.next());
}
You were probably expecting it to be equivalent to this ?
for (int i = 0; i < list.size(); i++) {
yourLoop.loopBody(list.get(i));
}
but this is not the case, and constructing the iterator takes additional time that you are observing.
Without knowing the List implementation, a specific answer can't really be given. For example, ArrayList is backed by an array, so calling get is essentially an array access.
Using the "foreach" version of a for loop on the other hand requires creating an Iterator. This is likely the cause for a slow down. Some implementations have complex implementation for an Iterator or ListIterator.
The answer then is a question of style and readability. Most Java programmers would say the foreach loop is much more readable and clear of your intent. And with some implementations of List (e.g. LinkedList) much faster.
I'm no expert in Collections, but setting up the iteration has got to be more expensive than simply getting a specific item.
By setting up a foreach, we don't know how many items there are in the collection, so it's going to set it up for iteration no matter how many items the list has.
IN general, if you're worried about speed, your fastest way to go if you know you're using ArrayList would be this:
int size = list.size();
for (int i=0;i<size;i++) {
Thing thing = list.get(i);
}
while the overhead of the "size" method is minimal, it is still overhead that need not be called in every loop. The get() method on ArrayList is O(1). This should give similar performance to an Iterator. If you look at the iterator code for ArrayList, it's quite simply and the only real extra overhead is from the Object creation, and concurrent modification checking.
For LinkedList, however, this type of loop would give horrible performance as the .get() method on LinkedList is O(n), and an Iterator would be much faster, since it's simply doing a pointer check and reassignment for each iteration which makes it O(1) for each call to next().

Remove elements from collection while iterating

AFAIK, there are two approaches:
Iterate over a copy of the collection
Use the iterator of the actual collection
For instance,
List<Foo> fooListCopy = new ArrayList<Foo>(fooList);
for(Foo foo : fooListCopy){
// modify actual fooList
}
and
Iterator<Foo> itr = fooList.iterator();
while(itr.hasNext()){
// modify actual fooList using itr.remove()
}
Are there any reasons to prefer one approach over the other (e.g. preferring the first approach for the simple reason of readability)?
Let me give a few examples with some alternatives to avoid a ConcurrentModificationException.
Suppose we have the following collection of books
List<Book> books = new ArrayList<Book>();
books.add(new Book(new ISBN("0-201-63361-2")));
books.add(new Book(new ISBN("0-201-63361-3")));
books.add(new Book(new ISBN("0-201-63361-4")));
Collect and Remove
The first technique consists in collecting all the objects that we want to delete (e.g. using an enhanced for loop) and after we finish iterating, we remove all found objects.
ISBN isbn = new ISBN("0-201-63361-2");
List<Book> found = new ArrayList<Book>();
for(Book book : books){
if(book.getIsbn().equals(isbn)){
found.add(book);
}
}
books.removeAll(found);
This is supposing that the operation you want to do is "delete".
If you want to "add" this approach would also work, but I would assume you would iterate over a different collection to determine what elements you want to add to a second collection and then issue an addAll method at the end.
Using ListIterator
If you are working with lists, another technique consists in using a ListIterator which has support for removal and addition of items during the iteration itself.
ListIterator<Book> iter = books.listIterator();
while(iter.hasNext()){
if(iter.next().getIsbn().equals(isbn)){
iter.remove();
}
}
Again, I used the "remove" method in the example above which is what your question seemed to imply, but you may also use its add method to add new elements during iteration.
Using JDK >= 8
For those working with Java 8 or superior versions, there are a couple of other techniques you could use to take advantage of it.
You could use the new removeIf method in the Collection base class:
ISBN other = new ISBN("0-201-63361-2");
books.removeIf(b -> b.getIsbn().equals(other));
Or use the new stream API:
ISBN other = new ISBN("0-201-63361-2");
List<Book> filtered = books.stream()
.filter(b -> b.getIsbn().equals(other))
.collect(Collectors.toList());
In this last case, to filter elements out of a collection, you reassign the original reference to the filtered collection (i.e. books = filtered) or used the filtered collection to removeAll the found elements from the original collection (i.e. books.removeAll(filtered)).
Use Sublist or Subset
There are other alternatives as well. If the list is sorted, and you want to remove consecutive elements you can create a sublist and then clear it:
books.subList(0,5).clear();
Since the sublist is backed by the original list this would be an efficient way of removing this subcollection of elements.
Something similar could be achieved with sorted sets using NavigableSet.subSet method, or any of the slicing methods offered there.
Considerations:
What method you use might depend on what you are intending to do
The collect and removeAl technique works with any Collection (Collection, List, Set, etc).
The ListIterator technique obviously only works with lists, provided that their given ListIterator implementation offers support for add and remove operations.
The Iterator approach would work with any type of collection, but it only supports remove operations.
With the ListIterator/Iterator approach the obvious advantage is not having to copy anything since we remove as we iterate. So, this is very efficient.
The JDK 8 streams example don't actually removed anything, but looked for the desired elements, and then we replaced the original collection reference with the new one, and let the old one be garbage collected. So, we iterate only once over the collection and that would be efficient.
In the collect and removeAll approach the disadvantage is that we have to iterate twice. First we iterate in the foor-loop looking for an object that matches our removal criteria, and once we have found it, we ask to remove it from the original collection, which would imply a second iteration work to look for this item in order to remove it.
I think it is worth mentioning that the remove method of the Iterator interface is marked as "optional" in Javadocs, which means that there could be Iterator implementations that throw UnsupportedOperationException if we invoke the remove method. As such, I'd say this approach is less safe than others if we cannot guarantee the iterator support for removal of elements.
Old Timer Favorite (it still works):
List<String> list;
for(int i = list.size() - 1; i >= 0; --i)
{
if(list.get(i).contains("bad"))
{
list.remove(i);
}
}
Benefits:
It only iterates over the list once
No extra objects created, or other unneeded complexity
No problems with trying to use the index of a removed item, because... well, think about it!
In Java 8, there is another approach. Collection#removeIf
eg:
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.removeIf(i -> i > 2);
Are there any reasons to prefer one approach over the other
The first approach will work, but has the obvious overhead of copying the list.
The second approach will not work because many containers don't permit modification during iteration. This includes ArrayList.
If the only modification is to remove the current element, you can make the second approach work by using itr.remove() (that is, use the iterator's remove() method, not the container's). This would be my preferred method for iterators that support remove().
Only second approach will work. You can modify collection during iteration using iterator.remove() only. All other attempts will cause ConcurrentModificationException.
You can't do the second, because even if you use the remove() method on Iterator, you'll get an Exception thrown.
Personally, I would prefer the first for all Collection instances, despite the additional overheard of creating the new Collection, I find it less prone to error during edit by other developers. On some Collection implementations, the Iterator remove() is supported, on other it isn't. You can read more in the docs for Iterator.
The third alternative, is to create a new Collection, iterate over the original, and add all the members of the first Collection to the second Collection that are not up for deletion. Depending on the size of the Collection and the number of deletes, this could significantly save on memory, when compared to the first approach.
I would choose the second as you don't have to do a copy of the memory and the Iterator works faster. So you save memory and time.
You can see this sample; If we think remove odd value from a list:
public static void main(String[] args) {
Predicate<Integer> isOdd = v -> v % 2 == 0;
List<Integer> listArr = Arrays.asList(5, 7, 90, 11, 55, 60);
listArr = listArr.stream().filter(isOdd).collect(Collectors.toList());
listArr.forEach(System.out::println);
}
use Iterator to remove object from collection other wise get
why not this?
for( int i = 0; i < Foo.size(); i++ )
{
if( Foo.get(i).equals( some test ) )
{
Foo.remove(i);
}
}
And if it's a map, not a list, you can use keyset()

iterator vs for loop and why iterator was introduced as we had for loop? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
What are the Advantages of Enhanced for loop and Iterator in Java ?
Is there a performance difference between a for loop and a for-each loop?
Below code shows that with both for loop as well as with iterator we can iterate the elements of collection then what is the difference between for loop and iterator and why we should use only iterator in case of collection
ArrayList<String> list=new ArrayList<String>();
list.add("dipu");
list.add("alok");
list.add("alok");
list.add("jyoti");
ArrayList<Integer> al=new ArrayList<Integer>();
al.add(1);
al.add(2);
String a[]={"a","b"};
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i));;
}
for(Integer t:al)
{
System.out.println(t);
}
for (Iterator iter = list.iterator(); iter.hasNext();)
{
System.out.println(iter.next());
}
Iterator it=list.iterator();
while(it.hasNext())
{
String st=it.next().toString();
System.out.println(st);
}
Though I'm not familiar with the Java Iterator, it seems very similar to .NET's IEnumerable.
The advantages of the enumerator/iterator are:
You don't have to know the size of the collection, which in some cases can require N steps to determine, increasing execution time (though it remains technically linear). Instead, you just keep moving to the next element until there aren't any.
Because the cardinality of the collection doesn't have to be known, iterators can allow collections to be generated dynamically, or "streamed" with elements being added while you begin work on what you already have. For instance, you could derive from Iterator and/or overload iterator getters to create classes that generate finite or infinite series "lazily", figuring out what each element in your enumerable collection is when you ask for it instead of when you define the collection. You could also set up a buffered stream, where you process records, packets, etc that you have received, while another thread or process works ahead of you to queue up more for you to work on.
Any collection that can provide an iterator can be traversed in exactly the same way, instead of having to know whether it's indexable, what the method or member is that defines size, etc etc etc. Iterator implementations thus provide an adapter to allow the same code to work on any collection passed to it.
Does Java have an equivalent to .NET extension methods (static methods that are not part of the class definition, but that work on instances of the type and can be called as if they were instance methods)? If so, you can define methods that take an Iterator and produce a result, which could be another Iterator. .NET's Linq library is based heavily on these, providing a very powerful collection-manipulation framework allowing for common operations to be chained together, each operating on the result of the previous operation.
Iterators are just generally safer I would say, no risk of accessing an index that isn't there. They also have a little more flexibility since you can go backwards and forwards with them whereas for loops only go one way and in many languages you cannot alter the value of the loop index within the loop (i.e. you cannot change the increment rate).
They are also the ONLY way to remove items from a collection while iterating through them. Removing an item from a collection while you were in a for loop through it would be disastrous and is generally not even allowed by Java, I forget what the exception is, but I've got one for doing that before.
Think about it, once you remove the item all the other ones shift down. Meanwhile on your next iteration your index was still incremented meaning 2 things.
First is that you will skip whatever the next element is as it was shifted to the position you just deleted from.
Second is that your loop will extend beyond the size of the collection which you have now altered.
I try to explain it with two short sentences:
With the enhanced for loop its easier to loop over it (more human readable..)
With the iterators it is possible to modify the list during the iteration, which is with the other methods not possible
The 'stream' you're iterating on might not even be indexable. That is, the iterator makes possible a very convenient 'lazy-evaluation' pattern where data isn't even loaded/constructed until the iterator asks for it. This is wonderful for repositories and database access, as well as networking.

Performance of traditional for loop vs Iterator/foreach in Java

Is there any performance testing results available in comparing traditional for loop vs Iterator while traversing a ArrayList,HashMap and other collections?
Or simply why should I use Iterator over for loop or vice versa?
Assuming this is what you meant:
// traditional for loop
for (int i = 0; i < collection.size(); i++) {
T obj = collection.get(i);
// snip
}
// using iterator
Iterator<T> iter = collection.iterator();
while (iter.hasNext()) {
T obj = iter.next();
// snip
}
// using iterator internally (confirm it yourself using javap -c)
for (T obj : collection) {
// snip
}
Iterator is faster for collections with no random access (e.g. TreeSet, HashMap, LinkedList). For arrays and ArrayLists, performance differences should be negligible.
Edit: I believe that micro-benchmarking is root of pretty much evil, just like early optimization. But then again, I think it's good to have a feeling for the implications of such quite trivial things. Hence I've run a small test:
iterate over a LinkedList and an ArrayList respecively
with 100,000 "random" strings
summing up their length (just something to avoid that compiler optimizes away the whole loop)
using all 3 loop styles (iterator, for each, for with counter)
Results are similar for all but "for with counter" with LinkedList. All the other five took less than 20 milliseconds to iterate over the whole list. Using list.get(i) on a LinkedList 100,000 times took more than 2 minutes (!) to complete (60,000 times slower). Wow! :) Hence it's best to use an iterator (explicitly or implicitly using for each), especially if you don't know what type and size of list your dealing with.
The first reason to use an iterator is obvious correctness. If you use a manual index, there may be very innocuous off-by-one errors that you can only see if you look very closely: did you start at 1 or at 0? Did you finish at length - 1? Did you use < or <=? If you use an iterator, it is much easier to see that it is really iterating the whole array. "Say what you do, do what you say."
The second reason is uniform access to different data structures. An array can be accessed efficiently through an index, but a linked list is best traversed by remembering the last element accessed (otherwise you get a "Shlemiel the painter"). A hashmap is even more complicated. By providing a uniform interface from these and other data structures (e.g., you can also do tree traversals), you get obvious correctness again. The traversing logic has to be implemented only once, and the code using it can concisely "say what it does, and do what it says."
Performance is similar in most cases.
However, whenever a code receives a List, and loops on it, there is well-known case:
the Iterator is way better for all List implementations that do not implement RandomAccess (example: LinkedList).
The reason is that for these lists, accessing an element by index is not a constant time operation.
So you can also consider the Iterator as more robust (to implementation details).
As always, performance should not be hide readability issues.
The java5 foreach loop is a big hit on that aspect :-)
Yes, it does make a difference on collections which are not random access based like LinkedList. A linked list internally is implemented by nodes pointing to the next(starting at a head node).
The get(i) method in a linked list starts from the head node and navigates through the links all the way to the i'th node. When you iterate on the linked list using a traditional for loop, you start again from the head node each time, thus the overall traversal becomes quadratic time.
for( int i = 0; i< list.size(); i++ ) {
list.get(i); //this starts everytime from the head node instead of previous node
}
While the for each loop iterates over the iterator obtained from the linked list and calls its next() method. The iterator maintains the states of the last access and thus does not start all the way from head everytime.
for( Object item: list ) {
//item element is obtained from the iterator's next method.
}
One of the best reasons to use an iterator over the i++ syntax is that not all data structures will support random access let alone have it perform well. You should also be programming to the list or collection interface so that if you later decided that another data structure would be more efficient you'd be able to swap it out without massive surgery. In that case (the case of coding to an interface) you won't necessarily know the implementation details and it's probably wiser to defer that to the data structure itself.
One of the reasons I've learned to stick with the for each is that it simplifies nested loops, especially over 2+ dimensional loops. All the i's, j's, and k's that you may end up manipulating can get confusing very quickly.
Use JAD or JD-GUI against your generated code, and you will see that there is no real difference. The advantage of the new iterator form is that it looks cleaner in your codebase.
Edit: I see from the other answers that you actually meant the difference between using get(i) versus an iterator. I took the original question to mean the difference between the old and new ways of using the iterator.
Using get(i) and maintaining your own counter, especially for the List classes is not a good idea, for the reasons mentioned in the accepted answer.
I don't believe that
for (T obj : collection) {
calculates .size() each time thru the loop and is therefore faster than
for (int i = 0; i < collection.size(); i++) {
+1 to what sfussenegger said. FYI, whether you use an explicit iterator or an implicit one (i.e. for each) won't make a performance difference because they compile to the same byte code.

Categories