My question is regarding optimization in java using the Android compiler. Will map.values() in the following be called every iteration, or will the Android compiler optimize it out.
LinkedHashMap<String, Object> map;
for (Object object : map.values())
{
//do something with object
}
Likewise here is another example. will aList.size() be called every iteration?
List<Object> aList;
for (int i = 0; i < aList.size(); i++)
{
object = aList.get(i);
//do something with i
}
And after all this, does it really matter if it calls the methods every iteration? Does Map.values(), and List.size() do much of anything?
In the first example, map.values() will be evaluated once. According to the Section 14.4.2 of the Java Language Specification, it is equivalent to:
for (Iterator<Object> i = map.values().iterator(); i.hasNext(); ) {
Object object = i.next();
// do something with object
}
In the second, aList.size() will be called every time the test is evaluated. For readability, it would be better to code it as:
for (Object object : aList) {
// do something with object
}
However, per the Android docs, this will be slower. Assuming that you aren't changing the list size inside the loop, the fastest another way would be to pull out the list size ahead of the loop:
final int size = aList.size();
for (int i = 0; i < size; i++)
{
object = aList.get(i);
//do something with i
}
This will be substantially faster (the Android docs linked to above say by a factor of 3) if aList happens to be an ArrayList, but is likely to be slower (possibly by a lot) for a LinkedList. It all depends on exactly what kind of List implementation class aList is.
Related
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.
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()];
}
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.
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
I have a vector of object and I need to compare them 1-by-1. That is:
for (Object o1 : list) {
for (Object o2 : list) {
//Do something with o1 and o2
}
}
Anyway using this approach I will compare any couple twice!
Using a "C" style approach, I would have done this:
for (i=0; i<n-1; i++) {
for (j=i+1; j<n; j++) {
//Do something with list[i] and list[j]
}
}
where n is the length of the list.
Is there a way to do this using for-each loop?
Addition
The usage of a for-each loop is not mandatory. Anyway, I'm concerned with performances issues. Does the for-each loop is faster than a simple for accessing index directly or not?
It is explicitly clear what your intent is with the C-like for loops - loop over every pair exactly once, so that the same pair with reversed members, e.g. (a, b) and (b, a) doesn't get processed again. That is what I would recommend; it works in Java just as well.
However, if you absolutely have to have the enhanced for loop, you can have the inner for loop operate over a sublist, with List's subList method, starting with the next element.
for (Object o1 : list) {
List<Object> subList = list.subList(list.indexOf(o1) + 1, list.size());
for (Object o2 : subList) {
//Do something with o1 and o2
}
}
The enhanced for loop is not appropriate in all situations. If you avoid using an index, just to use indexOf in the loop, your code will be less efficient (indexOf is a linear search) and non-idiomatic.
In my opinion, the best answer is to use the explicit indices.
for (i=0; i<n-1; i++) {
for (j=i+1; j<n; j++) {
// do something with list.get(i) and list.get(j)
}
}
One situation where you should avoid using get is if the List is a LinkedList, because get for a LinkedList is not a constant time operation. In this case I would do
List<Object> copy = new ArrayList<>(linkedList);
for (i=0; i<n-1; i++) {
for (j=i+1; j<n; j++) {
// do something with copy.get(i) and copy.get(j)
}
}
Assuming list is declared as List<Whatever>, you may achieve this behavior properly by using ListIterator rather than for-each loops:
ListIterator<Whatever> iteratorI = list.listIterator();
if (iteratorI.hasNext()) {
for (Whatever whateverI = iteratorI.next(); iteratorI.hasNext(); whateverI = iteratorI.next()) {
ListIterator<Whatever> iteratorJ = list.listIterator(iteratorI.nextIndex());
for (Whatever whateverJ = iteratorJ.next(); iteratorj.hasNext(); whateverJ = iteratorJ.next()) {
//do the comparison here...
}
}
}
The comments suggest you do it c-style or track an explicit index. Those are good suggestions. But if you insist on doing it with the new style for loop, there is a way:
for (Object o1 : list ) {
final int o1Index = list.indexOf(o1);
final int listSize = list.size();
for (Object o2 : list.subList(o1Index + 1, listSize)) {
//Do something with o1 and o2
}
}
The idea is that any o2 that comes before o1 in the list has already been processed, and you don't need to process o1 against itself. So you get a sublist consisting only of the elements following o1 and draw o2 from that sublist.
That will fail if any elements appear more than once in the list.
I've broken out o1Index and listSize for clarity, but in practice you'd probably in-line them.
Another option is to copy the original list and, before starting the inner loop, remove the front element each time. This properly accounts for duplicate elements, but takes more space.
final List<Object> newList = new ArrayList<>(list);
for (Object o1 : list) {
newList.remove(0);
for (Object o2 : newList) {
// Do something
}
}
You want performance?
Here you go!
The usage of a for-each loop is not mandatory
int s = list.size();
for(int i = 0; i < s-1; i++){
for(int n = i+1; n< s;n++){
if(list.get(i).equals(list.get(n))){
System.out.println("Duplicate");
}
}
}
You will never compare a combination twice.
Also to fully answer you question:
foreach does require more resources and reduces performance
To achieve the same result with foreach statement you'd create very much heap and slow the application down, also more instructions are processed by the CPU so you don't just loose memory but computing performance too.
Also try avoiding to call the size() method more than one time hence your list is not modified within this procedure. This also reduces CPU usage, but requires a very little bit more RAM (int s).
So your "C" style approach is almost optimal.
For ease i used java api calls, it also should be a ease to usw this example on your target framework.
EDIT: Improve performance even more by saving the list's size to reduce method calls.
This is a very specific case, comparison is just an operation of an infinity of other operations, other non commutative operations have a meaning for all combinations (this is just an example).
So there is no enhanced loop for such case.
Ok, this is a proof-of-concept I have on my head that has been bugging me for a few days:
Let's say I have:
List<String> a = new ArrayList<String>();
a.add("foo");
a.add("buzz");
a.add("bazz");
a.add("bar");
for (int i = 0; i < a.size(); i++)
{
String str = a.get(i);
if (!str.equals("foo") || !str.equals("bar")) a.remove(str);
}
this would end up with the list ["foo", "bazz", "bar"] because it would read the string at index 1 ("buzz"), delete it, the string at index 2 ("bazz") would jump to index 1 and it would be bypassed without being verified.
What I came up with was:
List<String> a = new ArrayList<String>();
a.add("foo");
a.add("buzz");
a.add("bazz");
a.add("bar");
for (int i = 0; i < a.size(); i++)
{
String str = a.get(i);
boolean removed = false;
if (!str.equals("foo") || !str.equals("bar"))
{
a.remove(str);
removed = true;
}
if (removed) i--;
}
It should work this way (atleast it does in my head lol), but messing with for iterators is not really good practice.
Other way I thought would be creating a "removal list" and add items to that list that needed to be removed from list a, but that would be just plain resource waste.
So, what is the best practice to remove items from a list efficiently?
Use an Iterator instead and use Iterator#remove method:
for (Iterator<String> it = a.iterator(); it.hasNext(); ) {
String str = it.next();
if (!str.equals("foo") || !str.equals("bar")) {
it.remove();
}
}
From your question:
messing with for iterators is not really good practice
In fact, if you code oriented to interfaces and use List instead of ArrayList directly, using get method could become into navigating through all the collection to get the desired element (for example, if you have a List backed by a single linked list). So, the best practice here would be using iterators instead of using get.
what is the best practice to remove items from a list efficiently?
Not only for Lists, but for any Collection that supports Iterable, and assuming you don't have an index or some sort of key (like in a Map) to directly access to an element, the best way to remove an element would be using Iterator#remove.
You have three main choices:
Use an Iterator, since it has that handy remove method on it. :-)
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (/*...you want to remove `it.next()`...*/) {
it.remove();
}
}
Loop backward through the list, so that if you remove something, it doesn't matter for the next iteration. This also has the advantage of only calling list.size() once.
for (int index = list.size() - 1; index >= 0; --index) {
// ...check and optionally remove here...
}
Use a while loop instead, and only increment the index variable if you don't remove the item.
int index = 0;
while (index < list.size()) {
if (/*...you want to remove the item...*/) {
list.removeAt(index);
} else {
// Not removing, move to the next
++index;
}
}
Remember that unless you know you're dealing with an ArrayList, the cost of List#get(int) may be high (it may be a traversal). But if you know you're dealing with ArrayList (or similar), then...
Your first example will likely cause off-by-one errors, since once you remove an object your list's indexes will change. If you want to be quick about it, use an iterator or List's own .remove() function:
Iterator<String> itr = yourList.iterator();
while (itr.hasNext()) {
if ("foo".equals(itr.next()) {
itr.remove();
}
}
Or:
yourList.remove("foo");
yourList.removeAll("foo"); // removes all
ArrayList.retainAll has a "smart" implementation that does the right thing to be linear time. You can just use list.retainAll(Arrays.asList("foo", "bar")) and you'll get the fast implementation in that one line.
I was expecting to find this in Java's LinkedList, since the point of linked lists is to be able to efficiently insert (and remove) anywhere (assuming you have some kind of pointer to the location where you want to insert or remove). I'm not finding anything in the API though. Am I overlooking something?
The closest thing I can find to this are the add and remove method in ListIterator. This has some limitations though. In particular, other iterators become invalid as soon as the underlying LinkedList is modified via remove, according to the API. This is born out in my tests as well; the following program results in a IllegalStateException:
import java.util.*;
public class RemoveFromLinkedList {
public static void main(String[] args) {
LinkedList<Integer> myList= new LinkedList<Integer>();
for (int i = 0; i < 10; ++i) {
myList.add(i);
}
ListIterator<Integer> i1 = myList.listIterator();
ListIterator<Integer> i2 = myList.listIterator();
for (int i = 0; i < 3; ++i) {
i1.next();
i2.next();
}
System.out.println("i1.next() should be 3: " + i1.next());
i1.remove();
i1.remove();
// Exception!
System.out.println("i2.next() should be 5: " + i2.next());
}
}
Ideally, what I'm expecting is something like this:
// In my imagination only. This is the way Java actually works, afaict.
// Construct two insertion/deletion points in LinkedList myLinkedList.
myIterator = myLinkedList.iterator();
for (...) {
myIterator.next();
}
start = myIterator.clone();
for (...) {
myIterator.next();
}
// Later...
after = myLinkedList.spliceAfter(myIterator, someOtherLinkedList);
// start, myIterator, and after are still all valid; thus, I can do this:
// Removes everything I just spliced in, as well as some other stuff before that.
myLinkedList.remove(start, after);
// Now, myIterator is invalid, but not start, nor after.
C++ has something like this for its list class (template). Only iterators pointing to moved elements become invalidated, not ALL iterators.
If you remove something with an iterator you cann still continue to use that same iterator. It's possible to do
iterator.remove();
iterator.next();
iterator.remove();
iterator.next();
That's the closest thing as far as I know.
You can do funny things with List.subList(startIndex, endIndex). With this you can clear a whole range in the "source" list. You can also use addAll at the sublist to insert new stuff into the source list.
If LinkedList has an efficient implementation for this - I don't know.
With java.util.LinkedList, the only way to refer to locations in the list for later efficient manipulation is an Iterator, and Iterators are invalidated if the underlying list is modified by something other than this Iterator.
If you really need that capability, you'll have to look beyond the Java API, or write it yourself.
ATTENTION: I CANNOT know if doSomething will remove the element or not. This is an exceptional case that my data structure needs to handle.
My problem is simples:
int size = list.size();
for(int i = 0; i < size; i++) {
MyObj mo = list.get(i);
mo.doSomething();
}
Now if doSomething() remove mo from the list, I eventually get an ArrayIndexOutOfBounds because the list has now shrunk.
What data structure should I use to allow iteration with the possibility of removing? I can NOT use an iterator here, in other words, I can NOT make doSomething return a boolean and call iterator.remove(). The data structure has to somehow handle the situation and continue to iterator through the rest of the elements still there.
EDIT: I CANNOT know if doSomething will remove the element or not. This is an exceptional case that my data structure needs to handle.
Part II => Making a smart listeners notifier to avoid code duplication everywhere
You can use an ArrayList, for example, as long as you update the index and size when something is removed.
List<MyObj> list = new ArrayList<MyObj>();
int size = list.size();
for(int i = 0; i < size; i++) {
MyObj mo = list.get(i);
mo.doSomething();
if (size > list.size()) {
size = list.size();
i--;
}
}
This only works if the item removed is the last one examined. For other changes to the list you will have to have more complicated logic.
What data structure should I use to allow iteration with the possibility of removing?
The simplest option is to take a copy of the list and iterate over that instead:
List<MyObj> copy = new ArrayList<MyObj>(list);
for (MyObj mo : copy) {
mo.doSomething();
}
Now it doesn't matter whether or not anything removes an idea from the original list - that won't change the copy of the list.
Another option is to use CopyOnWriteArrayList. You can then just iterate and remove or add items at will:
The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException. The iterator will not reflect additions, removals, or changes to the list since the iterator was created.
I think you should change you doSomething(). If mo.doSomething() can remove mo from l, you mo must know your l.
You can change the code like this:
Create a valid flag, inside of your MyObj. Only listen if valid.
while(list.hasNext()) {
MyObj mo = list.next()
if(mo.isValid()){
mo.doSomething();
} else {
list.remove();
}
}