Increment Key in a collection - java

I have a collection say
Map<Integer,Integer> myMap=new Map<Integer,Integer>();
myMap.put(1,"a");
myMap.put(2,"b");
myMap.put(3,"c");
My map currently has {1="a",2="b",3="c"}.
Suppose I want to put a value say myMap.put(1,"d")
So is there a way that I am able to add the existing key and incrementing the remaining key so my output map be like
{1="d",2="a",3="b",4="c"} ?

You will have to iterate over all the elements of the Map in order to modify the values for all the existing keys.
For example, woth Java 8 Streams you can produce a new Map where the keys are incremented, and then add the new Entry :
map = map.entrySet().stream().collect(Collectors.toMap(e->e.getKey()+1,e->e.getValue()));
map.put(1,"d");
However, if your keys are consecutive integers (as your example suggests), why not use an ArrayList<String> instead of a Map<Integer,String>? This will give you the functionality you want by simply calling list.add(0,"d"); (with the small difference of the indices starting at 0 instead of 1).

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/

Merge multiple Map and differentiate their value with different keys in java

EDIT: I have three maps with following format:
map1.put("aaa",1);
map1.put("bbb",1);
map1.put("ccc",1);
map2.put("aaa",2);
map2.put("bbb",3);
map3.put("ccc",6);
map3.put("ddd",6);
Now I want the result as list with following format:
[{"id":"aaa","map1count":"1","map2count":"2","map3count":"0"},
{"id":"bbb","map1count":"1","map2count":"0","map3count":"0"},
{"id":"ccc","map1count":"1","map2count":"0","map3count":"6"},
{"id":"ddd","map1count":"0","map2count":"0","map3count":"6"}]
How can I do this in java, help me to figure out.
you can create a class Count, with three members ex. mapCount1, mapCount2, mapCount3. Now create result map
HashMap<String, Count>() result = new HashMap<>();
Now you need to traverse these 3 maps, check map.containsKey(key), here key might be "aaa", "bbb", "ccc" etc. Now traverse first map, since map doesnt not contain any key, add key with value to result map. Now do this for 2nd, 3rd map, If key is there and then get value of count object and update count for mapCount2/3. At last for each key you can print count specific to each map.

2 Dimentional array with Hash-map

Is there a way to put a 2d array into a Hash map setup?
Example of the array would be two strings {"John", "red"},
{"George", "blue}
And I would want red to correspond to john etc.
I know I can use a nested loop to go through every item in the 2d array but how would then set it up to add them to the hash-map
hashMap.put("John", "red");
Assuming every array has 2 items in the form of {Name, Color}, you can just iterate over it
for(String[] combo : some2DArray){
someHashMap.Put(combo[0], combo[1]); // Or swap them, depending on what you
// want to be the key and the value
}
If you want to avoid the possibility of removing data because you happen to have two people with the same name there are a few approaches you can take:
Keep the old data
Keep the new data
Assign the new data to a new key
Combine the data in the same key
Keep the old data
Perform a check before using HashMap#put and see if the key already exists.
Only add the data if it doesn't exist yet.
Keep the new data
Use the current code, it will overwrite the old value.
Assign the new data to a new key
Create a new key based on your own rules and insert that.
Combine the data in the same key
Define your HashMap as HashMap<String, List<String>> and add the values to the list.
How about implementing a Pair class, so you can use HashMap<Pair<String,String>> ?
EDIT: Might be that I misunderstood your question, is that what yoe were asking?

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.

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

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.

Categories