Returning information from a Hashmap - java

Basically what I'm trying to do is store two values into a hashmap, i've tried a dictionary and failed with that as-well, anyhow, here we go.
private HashMap<Integer, Integer> dropTable = new HashMap<Integer, Integer>();
Then, in my code I have this
for(int npc = 0; npc < 10; npc++){
dropTable.put(npc, Constants.itemDrops[npc][1]);
}
Basically, what I'm trying to do is save the values in this manner (With the ItemID being what is returned in the itemDrops array
<ArrayIndex, ItemID>
How,ever when I try to return this information, i can't figure it out.
Here is how I attempted returning this value
for(int i = 0; i < dropTable.size(); i++) {
System.out.println("NPC: " + dropTable.get((Integer)i));
}
However, that returns null, and looking at it, it wont give me what I need.
How would I go about retrieving the Key/Value separately from the HashMap based on the Index of the HashMap? (If Hashmaps even have Index's, that's what I'm under the impression of)
===============
My idea of a hashmap.
<Integer>, <Integer> Index: 0
<Integer>, <Integer> Index: 1
etc...

HashMaps are unsorted, do not have indexes and the order features are returned during iteration is not guaranteed to be the order of insertion.
There are other Map objects available which provide some of these features. TreeMap is sorted for example.
All Maps provide a method keySet() which provides the set of Keys in an iterator and a similar values() Collection iterating over these objects is likely to provide the sort of behavour you wish.

First thing to aks, is a hashmap realy the data structure you need?
If not not then just use a simple List and use its get(index) method!
If Yes then you could use a Map implmentation - such as LinkedHashMap - that preserves the insert/put order. Then you can call values() of that map and iterate over it using enhanced for-loop, or probably also create a List and passing it the collection reurned if you need index access.

If you are looking to get a your objects according to an index - what you are really looking for is an ArrayList - which allows access by index, and is basically a dynamic array.
If you want to objects "attached" to the same index, you can use 2 ArrayLists (one for each type of object) - or use a Pair (from apache commons) as an element in the arraylist.

Related

Sort hasmap by value inside of a treemap

I have the following treemap
private TreeMap<Long, HashMap<Long, Entry>> index;
Entry contains:
int tf //count
ArrayList<long> off //positions
For each entry in the treemap, I would like to sort the hashmaps by tf. In the following picture, tf of [3] has a bigger value of tf of [0] so I would like to move it to be at the beggining. How can I do that?
You cannot order a HashMap. Trying to do so breaks the way a HashMap stores and finds the elements added to it
What you are trying to do here (as I understand it) is sorting the treemap by its value, while TreeMap can only sort by its keys. more details here - TreeMap sort by value
You may try writing your own sorting method and store the result of sort in a linkedHashMap instead of Treemap. That way you can be able to access the entries in the exact order you added that to the linkedHashMap.
Note: with each change happening to the original map, you ll need to sort it and move it to a different linkedHashMap. Which is very clumsy.
You may consider using different object model for your program.
I believe the fundamental problem with your question is that HashMaps are not sortable by definition. Secondly, a variable definition that is more generic may prove useful:
private SortedMap<Long, SortedMap<Entry, Long>> index;
Noticed I switched the order of Entry and Long. This is because Maps only sort based on the key. You'd have to either make Entry implement Comparable or provide a custom Comparator when you instantiate that Map.

Collection with index and hash access

I need a collection class which has both: quick index and hash access.
Now I have ArrayList. It has good index acces, but his contains method is not performant. HashSet has good contains implementation but no indexed acces. Which collection has both? Probably something from Apache?
Or should I create my own collection class which has both: ArrayList for indexed acces and HashSet for contains check?
Just for clarification: i need both get(int index) and contains(Object o)
If indexed access performance is not a problem the closest match is LinkedHashSet whose API says that it is
Hash table and linked list implementation of the Set interface, with predictable iteration order.
at least I dont think that the performance will be be worse than that of LinkedListPerformance. Otherwise I cannot see no alternative but your ArrayList + HashTable solution
If you are traversing the index from start to finish, I think this might satisfy your needs: LinkedHashSet
If you need to randomly access via the index, as well as hash access, if no-one else has a better suggestion I guess you can make your own collection which does both.
Do like this; use combination of Hash technique as well as list to get best of both worlds :)
class DataStructure<Integer>{
Hash<Integer,Integer> hash = new HashMap<Integer, Integer>();
List<Integer> list = new ArrayList<Integer>();
public void add(Integer i){
hash.add(i,i);
list.add(i);
}
public Integer get(int index){
return list.get(index);
}
...
} //used Integers to make it simpler
So object; you keep in HashMap/HashSet as well as ArrayList.
So if you want to use
contains method : call hashed contains method.
get an object with index: use array to return the value
Just make sure that you have both these collections in sync. And take care of updation/deletion in both data structures.
I don't know the exact lookup times, but maybe you could use some implementation of the Map interface. You could store you objects with map.put(objectHash, obj).
Then you could verify that you have a certain object with:
boolean contained = map.containsValue(obj);
And you can use the hash to lookup an object in the map:
MyObject object = map.get(objectHash);
Though, the only downfall is that you would need to know your hashes on this lookup call which may not be probably in your implementation.

Creating a custom iterator for a HashMap

I am trying to implement an iterator that will iterate through the HashMap and its duplicates. For example string.put("a", 1);
string.put("a", 2);
string.put("b", 3);
string.put("b", 4);
However with my iterator I only iterate twice, once for where the value is "a" and the other for "b". I'd like to make an iterator that will iterate 4 times throughout the whole Map.
EDIT: I kind of left out a lot of detail because I just wanted to see if this iterator was possible, but the code I'm writing is actually an abstraction of a map. For example, I have an add function which takes in parameter T. So for adding a string it would look like add("Hello"). By adding this string, it's key is "String" and its value is 1. If I call add("Hello") again it will bump up the value to 2. If I add it again, it will bump up its value to 3 and so on. I want to create an iterator that will iterate through all the stuff I have added.
Unfortunately, Java's Map interface doesn't allow for duplicate keys:
An object that maps keys to values. A
map cannot contain duplicate keys;
each key can map to at most one value.
Thus, when you try to put a key that already exists in the map, the new value replaces the old value; the reason your iterator iterates 2 times is because there are only 2 items.
If you want to keep duplicate keys (like "a" pointing to both 1 and 2), either you can have a Map of a List or Set, like
Map<String, List<Integer>> myMap;
Where the list or set that a key maps to contains all values, like myMap.get("a") would return a list that would look like [1,2].
Or use something like a MultiMap from either Google or Apache
For your problem, I believe you are saying that you want a special Map where:
The value for each key to be how many times the key was entered.
When you iterate over the map, you iterate over all the keys you added, for each time they were added.
You may want to look at how they implemented iterator() for HashMap, specifically looking at the internal private class HashIterator.
next() and hasNext() could maybe keep returning the key for as many times as specified by the value (i.e. if "Hello" maps to 2, your custom iterator() will return with next() "Hello" two times before moving onto the next key).
Map may not be an appropriate structure to use for what you're trying to do, but I wish you luck!
You can try using a Multimap from the guava library. java.util.HashMap allows to associate only one value with one key.
You can access an Iterator for your HashMap like this :
myHashMap.entrySet.iterator()
If you want to loop on all your objects, this is a faster way :
for(Object o : myHashMap.entrySet()) {
// do something with o
}
The problem in your case seems to come from the fact that a HashMap in java can't have identical keys, so your code add only two objects to the HashMap.

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.

Iterator is used in 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.

Categories