My question, is, whether the sequence of elements picked from a list will always be the same,
is this construction behaviour is deterministic for
java "List"s - descendants of java.util.List
2) question, if I use for(Object o: list) construction and inside the loop's body increment a variable,
will it be the index of list's elements? So, how it goes through list's elements, from 0 to size()-1 or chaotically?
List.get(i)
will always return this element?
3) question ( I suppose for the 2-nd question the answer will be negative, so:)
for (int i=0; i < list.size(); i++) {
}
is the best way if I need to save the index of an element and later get it back from a list by its id?
Overall:
I simply need to save a position in the list in every object's field.
object.setPosInList(currentIndexOfTheLoop)
Now clear?
Any descendant of List will provide an Iterator that iterates through the list in a deterministic proper order.
The for-each loop construct is compiled into code that uses the iterator() method which for a List is described in the following way in the api:
iterator
public Iterator iterator()
Returns an iterator over the elements in this list in proper sequence.
Specified by:iterator in interface Collection
Returns:an iterator over the elements in this list in proper sequence.
1) Yes
2) Yes
3) No.
Also note that on LinkedLists using get(i) is O(i) while getting the next element from an iterator (which is what for-each does) is O(1).
whether the sequence of elements picked from a list will always be the same
Yes. Quote from the API Javadoc:
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.
2:
how it goes through list's elements, from 0 to size()-1
Yes.
3: No, you generally don't need to iterate through the list manually to get to an indexed element. The most used List implementation is ArrayList, which is random access, i.e. you can access any of its elements directly, in constant time. For LinkedList, list.get(i) does iterate through the list till the desired element implicitly, as this implementation is not random-access.
According to the API doc contract of List.iterator():
Returns an iterator over the elements
in this list in proper sequence.
So yes, iteration over the elements of a List should happen from index 0 to size()-1. Theoretically, you could encounter an implementation that violates the contract, but then that's a bug in the implementation, not in your code.
Also, look at java.util.ListIterator.
List<Object> list = new ArrayList<Object>();
for(ListIterator<Object> it = list.listIterator(); it.hasNext(); )
{
Object o = it.next();
it.nextIndex();
it.prevIndex(); // etc
}
for(Object o : list) makes implicit use of the List's Iterator, returning elements in a deterministic order. for(int i = 0; i < list.size(); i++) also selects items from the List in a deterministic order, as by definition, Lists are ordered.
#MichaelBorgwardt Such an implementation would be broken - it doesn't satisfy the contract for List.iterator.
Related
So, in some question I was required to implement the following:
Data structure of fixed size (n=10), that is always ordered (descending, not that it matters), thread safe, and supports random access.
My solution was - using a TreeSet, whenever adding an element, if there are already n elements, remove the smallest element (if the new element if bigger than it) and add the new element. Otherwise, just add the new element.
When accessing a random index, use the TreeSet iterator to iterate until the required index.
I don't like this solution so much. So I thought of another solution:
Using an ArrayList, constructed with the size of n. Whenever trying to add an element, do a Collections.binarySearch() for the element and insert it if it doesn't exists, using the index returned from binarySearch. If after adding the element the list length is bigger than n (equals n+1 actually), remove the smallest element (which is on the end of the list). This way, we get log(n) for add (same as TreeSet from previous solution) and random access is O(1). Only thing I don't like about it is that the add() for an arbitrary index in the middle of the list requires shifting all the elements after it. (works well for small n but for big n maybe not?)
For both solutions I use ReentrantReadWriteLock - acquire writeLock() for add and readLock() for the get() / read operations.
Is there a better solution?
**
Collections.synchronizedList(List i) makes the passed argument a threadsafe List.
you can implement the comparable interface when creating your class and override compareTo() method in a way that it orders the element by descending order when you are adding them to the ArrayList<>() or you can go for Comparator class and overriding compare() method while sorting it.
In the total collection, only List(I) supports RandomAccess.
ArrayList<Employee> arrayList = Collections.synchronizedCollection(new ArrayList<Employee>(10));
and if you want the same item should not be added to the ArrayList use Comparator and return 0 when a new item (want to add) and last item (already added) is equal. handle the return value in such a manner that if (...==0){ don't add to the data ) else { add it }.
I hope I could give u some hint.
I was asked in an interview what is the advantage of using iterator over for loop or what is the advantage of using for loop over iterator?
Can any body please answer this?
First of all, there are 2 kinds of for loops, which behave very differently. One uses indices:
for (int i = 0; i < list.size(); i++) {
Thing t = list.get(i);
...
}
This kind of loop isn't always possible. For example, Lists have indices, but Sets don't, because they're unordered collections.
The other one, the foreach loop uses an Iterator behind the scenes:
for (Thing thing : list) {
...
}
This works with every kind of Iterable collection (or array)
And finally, you can use an Iterator, which also works with any Iterable:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
...
}
So you in fact have 3 loops to compare.
You can compare them in different terms: performance, readability, error-proneness, capability.
An Iterator can do things that a foreach loop can't. For example, you can remove elements while you're iterating, if the iterator supports it:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
if (shouldBeDeleted(thing) {
it.remove();
}
}
Lists also offer iterators that can iterate in both directions. A foreach loop only iterates from the beginning to an end.
But an Iterator is more dangerous and less readable. When a foreach loop is all you need, it's the most readable solution. With an iterator, you could do the following, which would be a bug:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
System.out.println(it.next().getFoo());
System.out.println(it.next().getBar());
}
A foreach loop doesn't allow for such a bug to happen.
Using indices to access elements is slightly more efficient with collections backed by an array. But if you change your mind and use a LinkedList instead of an ArrayList, suddenly the performance will be awful, because each time you access list.get(i), the linked list will have to loop though all its elements until the ith one. An Iterator (and thus the foreach loop) doesn't have this problem. It always uses the best possible way to iterate through elements of the given collection, because the collection itself has its own Iterator implementation.
My general rule of thumb is: use the foreach loop, unless you really need capabilities of an Iterator. I would only use for loop with indices with arrays, when I need access to the index inside the loop.
Iterator Advantage:
Ability to remove elements from Collections.
Ability to move forward and backward using next() and previous().
Ability to check if there more elements or not by using hasNext().
Loop was designed only to iterate over a Collection, so if you want just to iterate over a Collection, its better to use loop such as for-Each, but if you want more that that you could use Iterator.
The main difference between Iterator and the classic for loop, apart from the obvious one of having or not having access to the index of the item you're iterating, is that using Iterator abstracts the client code from the underlying collection implementation, allow me to elaborate.
When your code uses an iterator, either in this form
for(Item element : myCollection) { ... }
this form
Iterator<Item> iterator = myCollection.iterator();
while(iterator.hasNext()) {
Item element = iterator.next();
...
}
or this form
for(Iterator iterator = myCollection.iterator(); iterator.hasNext(); ) {
Item element = iterator.next();
...
}
What your code is saying is "I don't care about the type of collection and its implementation, I just care that I can iterate through its elements". Which is usually the better approach, since it makes your code more decoupled.
On the other hand, if you're using the classic for loop, as in
for(int i = 0; i < myCollection.size(); i++) {
Item element = myCollection.get(i);
...
}
Your code is saying, I need to know the type of collection, because I need to iterate through its elements in a specific way, I'm also possibly going to check for nulls or compute some result based on the order of iteration. Which makes your code more fragile, because if at any point the type of collection you receive changes, it will impact the way your code works.
Summing it up, the difference is not so much about speed, or memory usage, is more about decoupling your code so that is more flexible to cope with change.
if you access to data by number (e.g. "i"), it is fast when you use array. because it goes to element directly
But, other data structure (e.g. tree, list), it needs more time, because it start from first element to target element. when you use list. It needs time O(n). so, it is to be slow.
if you use iterator, compiler knows that where you are. so It needs O(1)
(because, it start from current position)
finally, if you use only array or data structure that support direct access(e.g. arraylist at java). "a[i]" is good. but, when you use other data structure, iterator is more efficient
Unlike other answers, I want to point another things;
if you need to perform the iteration in more than one place in your code, you will likely end up duplicating the logic. This clearly isn’t a very extensible approach. Instead, what’s needed is a way to separate the logic for selecting the data from the code that actually processes it.
An iterator solves these problems by providing a generic interface for looping over a set of data so that the underlying data structure or storage mechanism — such as an array- is hidden.
Iterator is a concept not an implementation.
An iterator provides a number of operations for traversing and accessing data.
An iterator may wrap any datastructure like array.
One of the more interesting and useful advantages of using iterators is the capability to wrap or decorate another iterator to filter the return values
An iterator may be thread safe while a for loop alone cannot be as it is accessing elements directly. The only popular thread-safety iterator is CopyOnWriteArrayList but it is well known and used often so worth mentioning.
This is from the book that it is https://www.amazon.com/Beginning-Algorithms-Simon-Harris/dp/0764596748
I stumbled on this question. The answer lies to the problems Iterator tries to solve:
access and traverse the elements of an aggregate object without exposing its representation
define traversal operations for an aggregate object without changing its interface
I would like to use colllection(List like one) in java which enables inserting between to elements?
Collections that are derivative of List contain an add method that takes an index so you can do this. java.util.ArrayList is a common one...
Use add method of List
to specify the position where you want to insert in a list
Adding an element between elements is an optional operation, which by default in AbstractCollection is not implemented and throws a specific exception. Derived by AbstractCollection, AbstractList was added with out of the box implementation for add(int, E) so any concrete implementation of AbstractList will have it.
More important, choose an implementation that fit your needs of performance regarding memory consumption, reads, writes, etc...
The List interface has a function add(index,element) which adds an element at the specified index.
ArrayList<String> list=new ArrayList<String>();
list.add("Java") ;
list.add("JSP") ;
list.add("STRUTS") ;
list.add("EJB") ;
list.add(2,"C++");
The list interface declares a function add(int index, E element).
The ArrayList, LinkedList class has implementations for the above method. So can use either one of the above as per your requirement to add an element in between.
List os = new ArrayList();
os.add('Windows');
os.add('Linux');
os.add('Mac');
os.add(1,'Android')
Android will be added at the 1st index of the list i:e will be the 2nd element as index begins with 0.
You can use the add(int index, Integer element) function of the list.
In this function, you can specifically put the element in the range of list using the index value.
Here is the sample:
List<Integer> sampleList = new ArrayList<Integer>();
sampleList.add(1);
sampleList.add(2);
sampleList.add(3); //sampleList now contains {1,2,3}
Now if you want to put it between 1 and 2.
sampleList.add(1,4); //sampleList now contains {1,4,2,3}
We put the value 4 between 1 and 2.
Array List is the best way to Insert/Update/Delete like operations easily.
And also you can use Linked List for that but it is used mostly for large data.
I'm using LinkedHashSet. I want to insert items at the 0th position, like:
Set<String> set = new LinkedHashSet<String>();
for (int i = 0; i < n; i++) {
set.add(0, "blah" + i);
}
I'm not sure how linked hash set is implemented, is inserting going to physically move all addresses of current items, or is it the same cost as inserting as in a linked-list implementation?
Thank you
------ Edit ---------------
Complete mess up by me, was referencing ArrayList docs. The Set interface has no add(index, object) method. Is there a way to iterate over the set backwards then? Right now to iterate I'm doing:
for (String it : set) {
}
can we do that in reverse?
Thanks
Sets are, by definition, independent of order. Thus, Set doesn't have add(int , Object) method available.
This is also true of LinkedHashSet http://download.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html
LinkedHashSet maintains insertion order and thus all elements are added at the end of the linked list. This is achieved using the LinkedHashMap. You can have a look at the method linkEntry in LinkedHashMap http://www.docjar.com/html/api/java/util/LinkedHashMap.java.html
Edit: in response to edited question
There is no API method available to do this. But you can do the following
Add Set to a List using new ArrayList(Set)
Use Collections.reverse(List)
Iterate this list
Judging by the source code of LinkedHashMap (which backs LinkedHashSet -- see http://www.docjar.com/html/api/java/util/LinkedHashMap.java.html ), inserts are cheap, like in a linked list.
To answer your latest question, there is no reverse iterator feature available from LinkedHashSet, even though internally the implementation uses a doubly linked list.
There is an open Request For Enhancement about this:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4848853
Mark Peters links to functionality available in guava, though their reverse list actually generates a reverse list.
As already mentioned, LinkedHashSet is build on LinkedHashMap, which is built on HashMap :) Javadocs says that it takes constant time to add an element into HashMap, assuming that your hash function is implemented properly. If your hash function is not implemented well, it may take up to O(n).
Iteration backwards in not supported at this moment.
You can't add elements to the front of a LinkedHashSet... it has no method such as add(int, Object) nor any other methods that make use of the concept of an "index" in the set (that's a List concept). It only provides consistent iteration order, based on the order in which elements were inserted. The most recently inserted element that was not already in the set will be the last element when you iterate over it.
And the Javadoc for LinkedHashSet explicitly states:
Like HashSet, it provides constant-time performance for the basic operations (add, contains and remove), assuming the hash function disperses elements properly among the buckets.
Edit: There is not any way to iterate over a LinkedHashSet in reverse short of something like copying it to a List and iterating over that in reverse. Using Guava you could do that like:
for (String s : Lists.reverse(ImmutableList.copyOf(set))) { ... }
Note that while creating the ImmutableList does require iterating over each element of the original set, the reverse method simply provides a reverse view and doesn't iterate at all itself.
This question already has answers here:
Does Java's foreach loop preserve order?
(2 answers)
Closed 7 years ago.
Does a java for-each loop guarantee that the elements will be presented in order if invoked on a list? In my tests it does seem to, but I can't seem to find this explicitly mentioned in any documentation
List<Integer> myList;// [1,2,3,4]
for (Integer i : myList) {
System.out.println(i.intValue());
}
#output
1,2,3,4
Yes. The foreach loop will iterate through the list in the order provided by the iterator() method. See the documentation for the Iterable interface.
If you look at the Javadoc for List you can see that a list is an "ordered collection" and that the iterator() method returns an iterator that iterates "in proper sequence".
The foreach loop will use the iterator built into the Collection, so the order you get results in will depend whether or not the Collection maintains some kind of order to the elements.
So, if you're looping over an ArrayList, you'll get items in the order they were inserted (assuming you didn't go on to sort the ArrayList). If you're looping over a HashSet, all bets are off, since HashSets don't maintain any ordering.
If you need to guarantee an order to the elements in the Collection, define a Comparator that establishes that order and use Collections.sort(Collection<T>, Comparator<? super T>).
Yes, the Java language specs ensure that
for (Iterator<Whatever> i = c.iterator(); i.hasNext(); )
whatEver(i.next());
is equivalent to
for (Whatever x : c)
whatEver(x);
no "change in ordering" is allowed.
You could use a for loop, a la for (int i = 0; i < myList.length(); i++) if you want to do it in an ordered manner. Though, as far as I know, foreach should do it in order.