How to get the number of occurrences of a key in HashMap? - java

I am have the Hashmap like this,
HashMap<String,String> epnSource = new HashMap<String, String>();
Now I have added the keys/values like this,
epnSource.put("10.3.2.227","EPN1");
epnSource.put("10.3.2.227","EPN2");
epnSource.put("10.3.2.166","EPN3");
epnSource.put("10.3.2.166","EPN4");
epnSource.put("10.3.2.161","EPN5");
I am trying to do every time before adding a value, I want to check number of occurrences of a key present in the HashMap. Suppose if key 10.3.2.227 has more than two occurrences I shouldn't added it and go for new one. Any suggestions will be helpful.

Suppose if value 10.3.2.227 has more than two occurrences ...
It won't. The way that you have implemented it, the "10.3.2.227" is a key of the Map, and a given key cannot appear more than once in a Map.
If you want a given key (e.g. "10.3.2.227") to map to multiple values (e.g. "EPN1" and "EPN1"), you need to use either a Map<String,Set<String>> or a MultiMap class from the Apache or Google/Guava collections libraries.

If the map previously contained a mapping for the key, the old value is replaced.
It is not possible duplicate key in HashMap.

Related

Combining remove and put method in LinkedHashMap

With a LinkedHashMap, when I try to reinsert same key with different value, it replaces the value and maintains the order of key i.e if I do this
Map<String,String> map = new LinkedHashMap<>();
map.put("a", "a");
map.put("b", "b");
map.put("c", "c");
map.put("d", "d");
map.values().stream().forEach(System.out::print);
Output: abcd
Now if I add in the map a different value with same key,the order remains the same i.e
map.put("b", "j");
map.values().stream().forEach(System.out::print);
Output: ajcd
Is there any other way? One is to remove and reinsert key with new value, which prints acdj as output. In my case I want to do it for multiple keys based on some property of object used as value?
Solution using streams would be preferable.
This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order). Note that insertion order is not affected if a key is re-inserted into the map
LinkedHashMap javadoc.
it keep track of the keys insertion, and if we add the Map.put javadoc :
If the map previously contained a mapping for the key, the old value is replaced by the specified value.
Map javadoc
The Entry is not replace, only the value is modified so the key remains the same.
You need to remove and then insert the value to update the ordering of the keys.
A HashMap is not sorted by either keys or values. What you are looking for is a TreeMap.
For a HashMap, the only guarantee is, that the keys are hashed and put in an array, based on their hash.
The LinkedHashMap, according to the Javadoc, creates an internal LinkedList, and tracks the original insertion order of entries. In other words, if you use LinkedHashMap, you won't, necessariely receive a 'sorted' list at all.
You have two options to work around this: Either use a TreeMap (or derivate thereof), or sort every time, you want to output the values. TreeMaps have an internal sorting, based on their keys. If the keys are compared to each other the way you'd expect (by comparing the Strings) then you get a properly ascending sorting, based on the keys. However this does not solve your problem, that you want to sort the values.
To solve your original problem, use a bidirectional TreeMap. Apache Commons4 implements such a map (https://commons.apache.org/proper/commons-collections/javadocs/api-4.3/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.html#values--)
It allows you to access both a key and a value set. But be aware that this map will not work for you, if your values are not unique. Like keys, all values in a bidirectional map need to be unique, because they need to serve as keys themselves.
From the Javadoc:
This map enforces the restriction that there is a 1:1 relation between keys and values, meaning that multiple keys cannot map to the same value. This is required so that "inverting" the map results in a map without duplicate keys. See the put(K, V) method description for more information.
Hashmap insertion is based on hashcode only. For example a key of "b" has a hashcode as 98.
for map.put("b", "b");
you inserting as a key "b" which has hascode 98.
so it will look like. 98 ---> holds value 'b'.
again if you try to put on same key "b" which has a hashcode 98 only.
so hashmap try to link on same hashcode only which is 98 ---> holds "j" as a value.
for know working of hashmap hashcode check out below link
https://www.geeksforgeeks.org/internal-working-of-hashmap-java/

Get neighbouring key/value pairs in tree map for given key

I'm using a tree map with data types Map < String, String > to store dates with its corresponding data. I want to be able to find out what the previous or next key are from a specified key. How can I get the neighboring key's from a specified key? I considered iterating through my Treemap but that is not very efficient.
If you have a given key, you can use the higherKey(key) and lowerKey(key) method, respectively.
There also are the corresponding xxxEntry() variants.

Java get values from LinkedHashMap with part of the key

I have the following key-value system (HashMap) , where String would be a key like this "2014/12/06".
LinkedHashMap<String, Value>
So, I can retrieve an item knowing the key, but what I'm looking for is a method to retrieve a list of the value which key matches partialy, I mean, how could I retrieve all the values of 2014?.
I would like to avoid solutions like, test every item in the list, brute-force, or similar.
thanks.
Apart from doing the brute-force solution of iterating over all the keys, I can think of two options :
Use a TreeMap, in which the keys are sorted, so you can find the first key that is >= "2014/01/01" (using map.getCeilingEntry("2014/01/01")) and go over all the keys from there.
Use a hierarchy of Maps - i.e. Map<String,Map<String,Value>>. The key in the outer Map would be the year. The key in the inner map would be the full date.
Not possible with LinkedHashMap only. If you can copy the keys to an ordered list you can perform a binary search on that and then do a LinkedHashMap.get(...) with the full key(s).
If you're only ever going to want to retrieve items using the first part of the key, then you want a TreeMap rather than a LinkedHashMap. A LinkedHashMap is sorted according to insertion order, which is no use for this, but a TreeMap is sorted according to natural ordering, or to a Comparator that you supply. This means that you can find the first entry that starts with 2014 efficiently (in log time), and then iterate through until you get to the first one that doesn't match.
If you want to be able to match on any part of the key, then you need a totally different solution, way beyond a simple Map. You'd need to look into full text searching and indexing. You could try something like Lucene.
You could refine a hash function for your values so that values with similar year would hash around similar prefixed hashes. That wouldn't be efficient (probably poor distribution of hashes) nor to the spirit of HashMaps. Use other map implementations such as TreeMaps that keep an order of your choice.

java hashMap<Integer,String> collision

I'm sorry if this question was already asked, but i don't fine an answer to my question.
I'm working on HashMap i put two values (7,"value test 1") (7,"value test 2)
According to the specification java API HashMap put the first values is replaced by the second .
My question is when comes the resolution of collision ? why my second value is not store in linkedList or store in another place in the hashMap ? Is it due to the equals or hascode method ??
Best Regards
This has nothing to do with hash collision. Hash collisions (ie., keys with the same hashcode()) are handled correctly by the HashMap. In your example, both keys are equal (ie., 7.equals(7) == true), so the old value is replaced.
In the following example
Map<Integer, String> map = new HashMap<>();
map.put(7, "value 1");
map.put(7, "value 2");
System.out.println(map.get(7));
what would you expect in the last line to happen?
Maybe you are looking for a multimap?
Apache Commons
Guava
Stackoverflow
Collision handling takes place if two different keys resolve to the same bucket in the hashmap. In that case the second entry would be put into the linked list.
In your case you replace the entry for the same key (7) and thus there is no collision.
If you need a map that contains multiple values per key either use a Map<key, Set<value>> (you can also use a List etc. instead of a Set) and handle adding/removing to that set yourself or use Apache Commons' MultiMap or Google Guava's Multimap, e.g. HashMultimap.

How to perform a group by (sql) in Java

I have a text file which looks like this:
code appearance
----------------
j4t8 1
fj89 3
pf6n 1
j4t8 5
And I want to sort by the codes which appear the most. As you can see (and since I want to perform a group by) there are duplicate codes, so using HashMap would be a problem (duplicate keys). Any ideas?
don't know if this is the best solution but you could create a map of a list like this:
Map<String, List<Integer>> map = new HahsMap<String, List<Integer>>();
if(map.contains.(key))
{
map.get(key).add(new_appearance_value);
}
else
{
List<Integer> app = new ArrayList<Integer>();
app.add(new_appearance_value);
map.put(key, app);
}
Where the map key would be the code and the values of appearance would go into the list.
Note: to determine which code has more appearances just check for the size of the list of each code.
You can use
HashMap map = new HashMap<String, List<Integer>>();
The appearances will be stored in a list associated with every code.
Then given a code you just retrieve the list of integers and iterate over it.
You need a Collection of Pair objects. Each pair holds the code and the appearance. You then sort the collection using a Comparator, which only compares the appearance in each Pair object, and disregards the code.
The Commons Collections MultiValueMap can be used to decorate another map, allowing it to have more than one value for a key.

Categories