Iterator is used in java? - java

In java while using the HashMap, they are using the Iterator class. But I can't understand for what purpose they are using Iterator in HashMap?

Entries in a Map are made up of key/value pairs. Iterators can be used to cycle through the set of keys (Map.keySet().iterator()), the set of values (Map.values().iterator(), or both (via the entrySet() method and the Map.Entry<K,V> interface).

For iteration, maybe?
In general, iterators are used to "remember" a point in the collection, so that you can do something to a current element and then move iterator to the next element, and so on...
When you write a code like
for(Value val : collection) { doSomething(val); }
You are implicitly using the collection's iterator.
It is roughly equivalent to writing something like
Iterator<Value> i = collection.iterator();
while(i.hasNext())
{
Value val = i.next();
doSomething(val);
}

Iterators should e used to read the elements from any kind of Collections like ArrayList, HAshMap etc.
They will help us to navigate through the Iterator Objects, if they are not there, how can we retrieve the elements from the collection?

You can iterate through the keys:
myMap.keySet().iterator();
Or you can iterate through the values:
myMap.values().iterator();
These two iterators offered by HashMap allow you to get values (for example) from the map even if you dont know the keys. Or even get a list of the keys.

Iterators provide a way to go over all elements in some order. Not very useful for HashMap, but for TreeMap iterator provides a way go over the elements in increasing order. Similarly for LinkedHashMap one can iterate the way it was inserted.

Related

Acessing a element in Treeset using index

Suppose there is a string treeset (ts)of elemnent 1,2,3,4,5,6,7,8,9,10.
Is there is any in built method in treeset so that i can access an element.
For eg accessing 3 can i do ts.[2]and accessing 8 ts.[7].(something like that).
i used this method:
Iterator<String> it = ts.iterator();
int i=0;
while(it.hasNext()) {
String ele=it.next();
if(i==2){
System.out.println(ele+"");
}
i++;
}
though when i ran it didn't showed any o/p but if i did i=0 then it showed all the o/p i.e 1,2,3,4,5,6,7,8,9,10.
Secondly can anyone tell me that when it is best to use hashset,treeset and linkedhashset
If you wanna access elements in your collection like ts[2], then you should better convert your collection into array using collection inbuilt method.
Otherwise, using iterator is the standard and efficient way to access elements in collection.
For second question, Hashset is used as hash table ; LinkedHashSet is used as hash table with elements stored in same way as inserted; TreeSet is used for collection using navigations.
For complete knowledge you must check Oracle documentation.
TreeSet is a NavigableSetwhich means you have an order of items (natural ordering as default, but you can define your own ordering relationship by using Comparator or Comparable interface) and you can navigate through items by this order. However there is no index mechanism. Basically a TreeSet is based on a TreeMap which is a red-black tree. In such a data structure indexes (element indexes, not indexes in the sense of efficient access) are not much meaningfull.
HashSet on the other hand is based on a HashMap which is a classical hash table implementation. In this data structure there is no order defined. You can look up each item at O(1) time though due to hash function used.
LinkedHashSet is a subclass of HashSet. Other then HashSet methods no new method is defined, so LinkedHashSet does not allow any more capability like natural order or indexes. However it has an auxilary linked list that keeps track of the order in which elements are inserted. In this way when you iterate over a LinkedHashSet by .iterator() method or a for loop you get elements in the order you inserted.
So basically a HashSet is more appropriate if you will access elements individually. Or being the simplest Set implementation you can use HashSet in generic cases. If you need to keep the order of insertion you need to use LinkedHashSet and if you have to enforce any custom ordering or natural ordering of items you should use TreeSet.

Retrieve N most relevant objects in Java TreeMap

According to this question I have ordered a Java Map, as follows:
ValueComparator bvc = new ValueComparator(originalMap);
Map<String,Integer> sortedMap = new TreeMap<String,Integer>(bvc);
sortedMap.putAll(originalMap);
Now, I would like to extract the K most relevant values from the map, in top-K fashion. Is there a highly efficient way of doing it without iterating through the map?
P.S., some similar questions (e.g., this) ask for a solution to the top-1 retrieval problem.
No, not if you use a Map. You'd have to iterate over it.
Have you considered using a PriorityQueue? It's Java's implementation of a heap. It has efficient operations for insertion of arbitrary elements and for removal of the "minimum". You might think about doing this here. Instead of a Map, you could put them into a PriorityQueue ordered by relevance, with the most relevant as the root. Then, to extract the K most relevant, you'd just pop K elements from the PriorityQueue.
If you need the map-like property (mapping from String to Integer), then you could write a class that internally keeps everything in both a PriorityQueue and a HashMap. When you insert, you insert into both; when you remove the minimal element, you pop from the PriorityQueue, and that then tells you which element you also need to remove from your HashMap. This will still give you log-time inserts and min-removals.

Exact meaning of the sentence.."Iterator itr=al.iterator(); "

Iterator itr=al.iterator();
how does this line eactly work? does it just store the arraylist al in iterator? Can anyone pls give me a detailed explanation.
Thanks in advance.
From the documentation :
An iterator over a collection. Iterator takes the place of Enumeration in the Java Collections Framework. Iterators differ from enumerations in two ways:
Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
Method names have been improved.
http://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html
Basically the iterator maintains a position for iterating over a collection. It can be used to iterate over a collection, with the option of modifying the collection while iterating over it without a ConcurrentModificationException.
Answer:
Returns an iterator over the elements in this list in proper sequence.
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.

Java HashMap and underlying values() collection

I was wondering if the Collection view of the values contained in a HashMap is kept ordered when the HashMap changes.
For example if I have a HashMap whose values() method returns L={a, b, c}
What happened to L if I add a new element "d" to the map?
Is it added at the end, i.e. if I iterate through the elements, it's the order kept?
In particular, if the addition of the new element "d" causes a rehash, will the order be kept in L?
Many thanks!
I was wondering if the Collection view of the values contained in a HashMap is kept ordered when the HashMap changes.
No, there is no such guarantee.
If this was the case, then the following program would output and ordered sequence from 1-100
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < 100; i++)
map.put(i, i);
System.out.println(map.values());
(and it doesn't).
There is a class that does precisely what you're asking for, and that is LinkedHashMap:
Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order).
If it doesn't say it in the JavaDoc then there are no guarantees about it. Different versions of Java could do different things. Don't depend on undocumented behaviour.
You might want to look at LinkedHashMap.
HashMap in Java aren't ordered, so I think it will be safe to say that values() won't return an ordered Collection.
LinkedHashMap is an ordered version of HashMap (insertion order), but I don't know it values() will return an ordered Collection. I think the best is to try.
Generally they is no guarantee of order when you are using HashMap. It might be in the order in which you add elements for a few elements but it would get reshuffled when there is a possibility of collision and it has to go with a collision resolution strategy.

Cost of inserting element at 0th position of LinkedHashSet?

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.

Categories