duplicate key value pairs [duplicate] - java

This question already has answers here:
Map implementation with duplicate keys
(20 answers)
Closed 9 years ago.
Is there a native data structure in java that accepts key value pairs and allows duplicates? I am creating a checklist of characters in a string but some characters occur more than once.
ex
j -> false
a -> false
v -> false
a -> false

You can simulate multiple key-value (KV) pairs by saving a list of values for each in a map. This is a standard implementation approach for "multivalue" maps.
So, if the key is a Character object and the value is Boolean, you can do
Map<Character, List<Boolean>> multimap = new HashMap<Character, List<Boolean>>();
and every time you want to add a new value to an existing KV pair in the map just call
multimap.get(key).add(value);
where key is the Character and value its corresponding Boolean value.
The Guava library by Google (free download) has a Multimap interface implemented in various ways, so essentially you can instantiate a MultiMap<Character, Boolean> map and use it accordingly. Similarly, you can get the Apache Commons Collections library and use its MultiValueMap class. You may also want to check the answers to a similar StackOverflow question, or another one.
If you only want to store one of each value per key, then a Set should be used in the place of the List.

Use a List of Pairs:
public class Pair<T, U> {
public final T key;
public final U value;
public Pair(T key, U value) {
this.key = key;
this.value = value;
}
}
public class YourApp {
public static void main(String[] args) {
List<Pair<Character, Boolean>> charList = new ArrayList<Pair<Character, Boolean>>();
charList.add(new Pair('j', false));
charList.add(new Pair('a', false));
charList.add(new Pair('v', false));
charList.add(new Pair('a', false));
for (Pair<Character, Boolean> pair : charList) {
System.out.println(pair.key + " -> " + pair.value);
}
}
}
With the selfwritten generic Pair class you can hold a key and a value of any type you want. If you're adding pairs to a List, you can even hold duplicates of pair entries.

You can use MultiMap<Character,Boolean> bcoz it allows duplicate key which exist in org.apache.commons.collections package.
or
You can use ArrayList and add the objects of the Class that contain attribute as char & boolean pair.

I do not know of a build in solution.
A quick alternative would be to use a simple ArrayList, and create an object that is a char/boolean pair that you can add to it.

commons.apache.org have MultiHashMap class. Try this one...!!!
MultiHashMap mp = new MultiHashMap();
mp.put("a", "1");
mp.put("b", "4");
mp.put("c", "2");
mp.put("a", "6");
List list = null;
Set set = mp.entrySet();
Iterator i = set.iterator();
while (i.hasNext()) {
Map.Entry<String, List<String>> me = (Map.Entry) i.next();
for(int j = 0 ; j< me.getValue().size(); j++ ){
System.out.println(me.getKey() +" : " +me.getValue().get(j));
}
}
}

Related

Comparing keys in HashMap and Values

I have a HashMap as follows-
HashMap<String, Integer> BC = new HashMap<String, Integer>();
which stores as keys- "tokens/tages" and as values- "frequency of each tokens/tags".
Example-
"the/at" 153
"that/cs" 45
"Ann/np" 3
I now parse through each key and check whether for same token say "the" whether it's associated with more than one tag and then take the largest of the two.
Example-
"the/at" 153
"the/det" 80
Then I take the key- "the/at" with value - 153.
The code that I have written to do so is as follows-
private HashMap<String, Integer> Unigram_Tagger = new HashMap<String, Integer>();
for(String curr_key: BC.keySet())
{
for(String next_key: BC.keySet())
{
if(curr_key.equals(next_key))
continue;
else
{
String[] split_key_curr_key = curr_key.split("/");
String[] split_key_next_key = next_key.split("/");
//out.println("CK- " + curr_key + ", NK- " + next_key);
if(split_key_curr_key[0].equals(split_key_next_key[0]))
{
int ck_v = 0, nk_v = 0;
ck_v = BC.get(curr_key);
nk_v = BC.get(next_key);
if(ck_v > nk_v)
Unigram_Tagger.put(curr_key, BC.get(curr_key));
else
Unigram_Tagger.put(next_key, BC.get(next_key));
}
}
}
}
But this code is taking too long to compute since the original HashMap 'BC' has 68442 entries which comes approximately to its square = 4684307364 times (plus some more).
My question is this- can I accomplish the same output using a more efficient method?
Thanks!
Create a new
Map<String,Integer> highCount = new HashMap<>();
that will map tokens to their largest count.
Make a single pass through the keys.
Split each key into its component tokens.
For each token, look in highMap. If the key does not exist, add it with its count. If the entry already exists and the current count is greater than the previous maximum, replace the maximum in the map.
When you are done with the single pass the highCount will contain all the unique tokens along with the highest count seen for each token.
Note: This answer is intended to give you a starting point from which to develop a complete solution. The key concept is that you create and populate a new map from token to some "value" type (not necessarily just Integer) that provides you with the functionality you need. Most likely the value type will be a new custom class that stores the tag and the count.
The slowest part of your current method is due to the pairwise comparison of keys. First, define a Tuple class:
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
}
Thus you can try an algorithm that does:
Initializes a new HashMap<String, Tuple<String, Integer>> result
Given input pair (key, value) from the old map, where key = "a/b", check whether result.keySet().contains(a) and result.keySet().contains(b).
If both a and b is not present, result.put(a, new Tuple<String, Integer>(b, value) and result.put(b, new Tuple<String, Integer>(a, value))
If a is present, compare value and v = result.get(a). If value > v, remove a and b from result and do step 3. Do the same for b. Otherwise, get the next key-value pair.
After you have iterated through the old hash map and inserted everything, then you can easily reconstruct the output you want by transforming the key-values in result.
A basic thought on the algorithm:
You should get the entrySet() of the HashMap and convert it to a List:
ArrayList<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
Now you should sort the list by the keys in alphabetical order. We do that because the HashMap has no order, so you can expect that the corresponding keys might be far apart. But by sorting them, all related keys are directly next to each other.
Collections.sort(list, Comparator.comparing(e -> e.getKey()));
The entries "the/at" and "the/det" will be next to each other, thanks to sorting alphabetically.
Now you can iterate over the entire list while remembering the best item, until you find a better one or you find the first item which has not the same prefix (e.g. "the").
ArrayList<Map.Entry<String, Integer>> bestList = new ArrayList<>();
// The first entry of the list is considered the currently best item for it's group
Map.Entry<String, Integer> currentBest = best.get(0);
String key = currentBest.getKey();
String currentPrefix = key.substring(0, key.indexOf('/'));
for (int i=1; i<list.size(); i++) {
// The item we compare the current best with
Map.Entry<String, Integer> next = list.get(i);
String nkey = next.getKey();
String nextPrefix = nkey.substring(0, nkey.indexOf('/'));
// If both items have the same prefix, then we want to keep the best one
// as the current best item
if (currentPrefix.equals(nextPrefix)) {
if (currentBest.getValue() < next.getValue()) {
currentBest = next;
}
// If the prefix is different we add the current best to the best list and
// consider the current item the best one for the next group
} else {
bestList.add(currentBest);
currentBest = next;
currentPrefix = nextPrefix;
}
}
// The last one must be added here, or we would forget it
bestList.add(currentBest);
Now you should have a list of Map.Entry objects representing the desired entries. The complexity should be n(log n) and is limited by the sorting algorithm, while grouping/collection the items has a complexity of n.
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class Point {
public static void main(String[] args) {
HashMap<String, Integer> BC = new HashMap<>();
//some random values
BC.put("the/at",5);
BC.put("Ann/npe",6);
BC.put("the/atx",7);
BC.put("that/cs",8);
BC.put("the/aty",9);
BC.put("Ann/np",1);
BC.put("Ann/npq",2);
BC.put("the/atz",3);
BC.put("Ann/npz",4);
BC.put("the/atq",0);
BC.put("the/atw",12);
BC.put("that/cs",14);
BC.put("that/cs1",16);
BC.put("the/at1",18);
BC.put("the/at2",100);
BC.put("the/at3",123);
BC.put("that/det",153);
BC.put("xyx",123);
BC.put("xyx/w",2);
System.out.println("\nUnsorted Map......");
printMap(BC);
System.out.println("\nSorted Map......By Key");
//sort original map using TreeMap, it will sort the Map by keys automatically.
Map<String, Integer> sortedBC = new TreeMap<>(BC);
printMap(sortedBC);
// find all distinct prefixes by spliting the keys at "/"
List<String> uniquePrefixes = sortedBC.keySet().stream().map(i->i.split("/")[0]).distinct().collect(Collectors.toList());
System.out.println("\nuniquePrefixes: "+uniquePrefixes);
TreeMap<String,Integer> mapOfMaxValues = new TreeMap<>();
// for each prefix from the list above filter the entries from the sorted map
// having keys starting with this prefix
//and sort them by value in descending order and get the first which will have the highst value
uniquePrefixes.stream().forEach(i->{
Entry <String,Integer> e =
sortedBC.entrySet().stream().filter(j->j.getKey().startsWith(i))
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).findFirst().get();
mapOfMaxValues.put(e.getKey(), e.getValue());
});
System.out.println("\nmapOfMaxValues...\n");
printMap(mapOfMaxValues);
}
//pretty print a map
public static <K, V> void printMap(Map<K, V> map) {
map.entrySet().stream().forEach((entry) -> {
System.out.println("Key : " + entry.getKey()
+ " Value : " + entry.getValue());
});
}
}
// note: only tested with random values provided in the code
// behavior for large maps untested

What is the Java equivalent of a Python Dictionary [duplicate]

This question already has answers here:
Java Equivalent to Python Dictionaries
(4 answers)
Closed 6 years ago.
I have a Dictionary in Python say
{ SERVER1 : [ (list1),(list2),....
SERVER2 : [ (list2a),(list2b) ] }
Is it same can be implemented in Java ?
I need to check each key if exist then I need to add the list to that key like appending the existing value without overriding
Also need to read the key and value and traverse through each value of list
Kindly assist. Sorry to ask these question as it is my first program in Java
In java, dictionaries are defined with the Map interface. The common implementations are TreeMap and HashMap:
Map<String,List<String>> servers = new HashMap<>();
servers.put("SERVER1", new ArrayList<String>());
servers.get("SERVER1").add("list1");
servers.get("SERVER1").add("list2");
...
Similarly, ArrayList and LinkedList are common implementations of the List interface.
Because you want to save each value associated with a key, you need a HashMap that contains ArrayLists for values. This object should do what you need:
public class HashOfLists<K, V> {
HashMap<K, ArrayList<V>> map = new HashMap<>();
public ArrayList<V> get(K key) {
return map.get(key);
}
public void put(K key, V value) {
ArrayList<V> existingValues = get(key);
if (existingValues == null) existingValues = new ArrayList<>();
existingValues.add(value);
map.put(key, existingValues);
}
}
To use it you would do something a bit like this:
HashOfLists<String, String> servers = new HashOfLists<>();
servers.put("SERVER3", "PROCESS A");
servers.put("SERVER3", "PROCESS B");
//Getting a list containing "PROCESS A" and "PROCESS B"
ArrayList<String> processes = servers.get("SERVER3");

Deduplicating HashMap Values

I'm wondering if anyone knows a good way to remove duplicate Values in a LinkedHashMap? I have a LinkedHashMap with pairs of String and List<String>. I'd like to remove duplicates across the ArrayList's. This is to improve some downstream processing.
The only thing I can think of is keeping a log of the processed Values as I iterate over HashMap and then through the ArrayList and check to see if I've encountered a Value previously. This approach seems like it would degrade in performance as the list grows. Is there a way to pre-process the HashMap to remove duplicates from the ArrayList values?
To illustrate...if I have
String1>List1 (a, b, c)
String2>List2 (c, d, e)
I would want to remove "c" so there are no duplicates across the Lists within the HashMap.
I believe creating a second HashMap, that can be sorted by values (Alphabetically, numerically), then do a single sweep through the sorted list, to check to see if the current node, is equivalent to the next node, if it is, remove the next one, and keep the increment at the same, so it will remain at the same index of that sorted list.
Or, when you are adding values, you can check to see if it already contains this value.
Given your clarification, you want something like this:
class KeyValue {
public String key;
public Object value;
KeyValue(String key, Object value) {
this.key = key;
this.value = value;
}
public boolean equals(Object o) {
// boilerplate omitted, only use the value field for comparison
}
public int hashCode() {
return value.hashCode();
}
}
public void deduplicate() {
Map<String, List<Object>> items = new HashMap<String, List<Object>>();
Set<KeyValue> kvs = new HashSet<KeyValue>();
for (Map.Entry<String, List<Object>> entry : items.entrySet()) {
String key = entry.getKey();
List<Object> values = entry.getValue();
for (Object value : values) {
kvs.add(new KeyValue(key, value));
}
values.clear();
}
for (KeyValue kv : kvs) {
items.get(kv.key).add(kv.value);
}
}
Using a set will remove the duplicate values, and the KeyValue lets us preserve the original hash key while doing so. Add getters and setters or generics as needed. This will also modify the original map and the lists in it in place. I also think the performance for this should be O(n).
I'm assuming you need unique elements (contained in your Lists) and not unique Lists.
If you need no association between the Map's key and elements in its associated List, just add all of the elements individually to a Set.
If you add all of the Lists to a Set, it will contain the unique List objects, not unique elements of the Lists, so you have to add the elements individually.
(you can, of course, use addAll to make this easier)
So, to clarify... You essentially have K, [V1...Vn] and you want unique values for all V?
public void add( HashMap<String, List> map, HashMap<Objet, String> listObjects, String key, List values)
{
List uniqueValues= new List();
for( int i = 0; i < values.size(); i++ )
{
if( !listObjects.containsKey( values.get(i) ) )
{
listObjects.put( values.get(i), key );
uniqueValues.add( values.get(i) );
}
}
map.put( key, uniqueValues);
}
Essentially, we have another HashMap that stores the list values and we remove the non-unique ones when adding a list to the map. This also gives you the added benefit of knowing which list a value occurs in.
Using Guava:
Map<Value, Key> uniques = new LinkedHashMap<Value, Key>();
for (Map.Entry<Key, List<Value>> entry : mapWithDups.entrySet()) {
for (Value v : entry.getValue()) {
uniques.put(v, entry.getKey());
}
}
ListMultimap<K, V> uniqueLists = Multimaps.invertFrom(Multimaps.forMap(uniques),
ArrayListMultimap.create());
Map<K, List<V>> uniqueListsMap = (Map) uniqueLists.asMap(); // only if necessary
which should preserve the ordering of the values, and keep them unique. If you can use a ListMultimap<K, V> for your result -- which you probably can -- then go for it, otherwise you can probably just cast uniqueLists.asMap() to a Map<K, List<V>> (with some abuse of generics, but with guaranteed type safety).
As other have noted, you could check the value as you add, but, if you have to do it after the fact:
static public void removeDups(Map<String, List<String>> in) {
ArrayList<String> allValues = new ArrayList<String>();
for (List<String> inValue : in.values())
allValues.addAll(inValue);
HashSet<String> uniqueSet = new HashSet<String>(allValues);
for (String unique : uniqueSet)
allValues.remove(unique);
// anything left over was a duplicate
HashSet<String> nonUniqueSet = new HashSet<String>(allValues);
for (List<String> inValue : in.values())
inValue.removeAll(nonUniqueSet);
}
public static void main(String[] args) {
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
map.put("1", new ArrayList(Arrays.asList("a", "b", "c", "a")));
map.put("2", new ArrayList(Arrays.asList("d", "e", "f")));
map.put("3", new ArrayList(Arrays.asList("a", "e")));
System.out.println("Before");
System.out.println(map);
removeDups(map);
System.out.println("After");
System.out.println(map);
}
generates an output of
Before
{3=[a, e], 2=[d, e, f], 1=[a, b, c, a]}
After
{3=[], 2=[d, f], 1=[b, c]}

Map.Entry: How to use it?

I'm working on creating a calculator.
I put my buttons in a HashMap collection and when I want to add them to my class, which extends JPanel, I don't know how can I get the buttons from my collection.
So I found on the internet the 2 last lines of my code, but I don't know their meaning.
Here is my code:
import java.awt.Component;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JPanel;
public class PanneauCalcul extends JPanel {
private HashMap<String, JButton> listbouton = new HashMap<String, JButton>() ;
public PanneauCalcul() {
for(int i = 0; i < 10; i ++) {
listbouton.put("num" + i, new JButton("" + i)) ;
}
listbouton.put("add", new JButton("+")) ;
listbouton.put("soustract", new JButton("-")) ;
listbouton.put("multiply", new JButton("x")) ;
listbouton.put("divise", new JButton("/")) ;
listbouton.put("equal", new JButton("=")) ;
Set entrys = listbouton.entrySet() ;
Iterator iter = entrys.iterator() ;
while(iter.hasNext()) {
Map.Entry me = (Map.Entry)iter.next(); //don't understand
this.add((Component) me.getValue()) ; //don't understand
}
EcouteCalcul ecout = new EcouteCalcul(this) ;
}
}
I don't understand how can we use Map.Entry--which is an interface--without redefining Map.Entry's functions.
Map.Entry is a key and its value combined into one class. This allows you to iterate over Map.entrySet() instead of having to iterate over Map.keySet(), then getting the value for each key. A better way to write what you have is:
for (Map.Entry<String, JButton> entry : listbouton.entrySet())
{
String key = entry.getKey();
JButton value = entry.getValue();
this.add(value);
}
If this wasn't clear let me know and I'll amend my answer.
Note that you can also create your own structures using a Map.Entry as the main type, using its basic implementation AbstractMap.SimpleEntry. For instance, if you wanted to have an ordered list of entries, you could write:
List<Map.Entry<String, Integer>> entries = new ArrayList<>();
entries.add(new AbstractMap.SimpleEntry<String, Integer>(myStringValue, myIntValue));
And so on. From there, you have a list of tuples. Very useful when you want ordered tuples and a basic Map is a no-go.
This code is better rewritten as:
for( Map.Entry me : entrys.entrySet() )
{
this.add( (Component) me.getValue() );
}
and it is equivalent to:
for( Component comp : entrys.getValues() )
{
this.add( comp );
}
When you enumerate the entries of a map, the iteration yields a series of objects which implement the Map.Entry interface. Each one of these objects contains a key and a value.
It is supposed to be slightly more efficient to enumerate the entries of a map than to enumerate its values, but this factoid presumes that your Map is a HashMap, and also presumes knowledge of the inner workings (implementation details) of the HashMap class. What can be said with a bit more certainty is that no matter how your map is implemented, (whether it is a HashMap or something else,) if you need both the key and the value of the map, then enumerating the entries is going to be more efficient than enumerating the keys and then for each key invoking the map again in order to look up the corresponding value.
A Map consists of key/value pairs. For example, in your code, one key is "Add" and the associated value is JButton("+"). A Map.Entry is a single key/value pair contained in the Map. It's two most-used methods are getKey() and getValue(). Your code gets all the pairs into a Set:
Set entrys = listbouton.entrySet() ;
and iterates over them. Now, it only looks at the value part using me.getValue() and adds them to your PanneauCalcul
this.add((Component) me.getValue()) ; //don't understand
Often this type of loop (over the Map.Entry) makes sense if you need to look at both the key and the value. However, in your case, you aren't using the keys, so a far simpler version would be to just get all the values in your map and add them. e.g.
for (JButton jb:listbouton.values()) {
this.add(jb);
}
One final comment. The order of iteration in a HashMap is pretty random. So the buttons will be added to your PanneauCalcul in a semi-random order. If you want to preserve the order of the buttons, you should use a LinkedHashMap.
A Map is a collection of Key + Value pairs, which is visualized like this:
{[fooKey=fooValue],barKey=barValue],[quxKey=quxValue]}
The Map interface allows a few options for accessing this collection: The Key set [fooKey, barKey,quxKey], the Value set [fooValue, barValue, quxValue] and finally entry Set [fooKey=fooValue],barKey=barValue],[quxKey=quxValue].
Entry set is simply a convenience to iterate over the key value pairs in the map, the Map.Entry is the representation of each key value pair. An equivalent way to do your last loop would be:
for (String buttonKey: listbouton.keySet()) {
this.add(listbouton.get(buttonKey)) ;
}
or
for (JButton button: listbouton.values()) {
this.add(button) ;
}
Hash-Map stores the (key,value) pair as the Map.Entry Type.As you know that Hash-Map uses Linked Hash-Map(In case Collision occurs). Therefore each Node in the Bucket of Hash-Map is of Type Map.Entry. So whenever you iterate through the Hash-Map you will get Nodes of Type Map.Entry.
Now in your example when you are iterating through the Hash-Map, you will get Map.Entry Type(Which is Interface), To get the Key and Value from this Map.Entry Node Object, interface provided methods like getValue(), getKey() etc. So as per the code, In your Object you are adding all operators JButtons viz (+,-,/,*,=).
Map.Entry interface helps us iterating a Map class
Check this simple example:
public class MapDemo {
public static void main(String[] args) {
Map<Integer,String> map=new HashMap();
map.put(1, "Kamran");
map.put(2, "Ali");
map.put(3, "From");
map.put(4, "Dir");
map.put(5, "Lower");
for(Map.Entry m:map.entrySet()){
System.out.println(m.getKey()+" "+m.getValue());
}
}
}
public HashMap<Integer,Obj> ListeObj= new HashMap<>();
public void addObj(String param1, String param2, String param3){
Obj newObj = new Obj(param1, param2, param3);
this.ListObj.put(newObj.getId(), newObj);
}
public ArrayList<Integer> searchdObj (int idObj){
ArrayList<Integer> returnList = new ArrayList<>();
for (java.util.Map.Entry<Integer, Obj> e : this.ListObj.entrySet()){
if(e.getValue().getName().equals(idObj)) {
returnList.add(e.getKey());
}
}
return returnList;
}

Java code to Prevent duplicate <Key,Value> pairs in HashMap/HashTable

I have a HashMap as below (assuming it has 10,0000 elements)
HashMap<String,String> hm = new HashMap<String,String>();
hm.put("John","1");
hm.put("Alex","2");
hm.put("Mike","3");
hm.put("Justin","4");
hm.put("Code","5");
==========================
Expected Output
==========================
Key = John",Value = "1"
Key = Alex",Value = "2"
Key = Mike",Value = "3"
Key = Justin",Value = "4"
Key = Code",Value = "5"
===========================
I need Java code to prevent Addition of Duplicate <Key,Value> Pairs in HashMap such
that below conditions are staisfied.
1> hm.put("John","1"); is not accepted/added again in the Map
2> hm.put("John","2"); is not accepted/added again in the Map
Hope its clear.
Java code provided will be appreciated.(generic solution needed since i can add any duplicate to the existing map)
You can wrap HashMap in a class, which delegates put, get, and other methods you use from HashMap. This method is wasteful but safe, since it doesn't depend on the internal implementation of HashMap, AbstractMap. The code below illustrates put, get delegating:
public class Table {
protected java.util.HashMap<String, Integer> map =
new java.util.HashMap<String, Integer>();
public Integer get(String key) { return map.get(key); }
public Integer put(String key, Integer value) {
if (map.containsKey(key)) {
// implement the logic you need here.
// You might want to return `value` to indicate
// that no changes applied
return value;
} else {
return map.put(key, value);
}
}
// other methods goes here
}
Another option is to make a class which extends HashMap, and depend on its internal implementation. Java 1.6 sources shows that put is called only in putAll in HashMap, so you can simply override put method:
public class Table extends java.util.HashMap<String, Integer> {
public Integer put(String key, Integer value) {
if (containsKey(key)) {
// implement the logic you need here.
// You might want to return `value` to indicate
// that no changes applied
return value;
} else {
return super.put(key, value);
}
}
}
Another option is similar to the first, and can make an utility method in your class which contains the HashMap instance and call that method wherever you need put something to your map:
public final Integer putToMap(String key, String value) {
if(this.map.containsKey(key)) {
return value;
} else {
return this.map.put(key, value);
}
}
This is an "inline" equivalent of checking manually.
I note that you clarify the question by suggesting you might have "100000000 elements". You still won't have duplicates in the HashMap, because, as two other posters have pointed out, you can't get duplicate keys in a Map. I'm still not sure we understand the question, though, as it's not at all clear how you expected to generate the block titled "Output", or what you intend to do with it.
This may be old question but I thought to share my experience with this. As others pointed out you can't have the same element in a HashMap. By default HashMap will not allow this but there are some cases that you could end up with two or more elements are almost alike that you do not accept but HashMap will. For example, the following code defines a HashMap that takes an array of integers as a key then add :
HashMap<int[], Integer> map1 = new HashMap<>();
int[] arr = new int[]{1,2,3};
map1.put(arr, 4);
map1.put(arr, 4);
map1.put(arr, 4);
At this point, the HashMap did not allow dublicating the key and map1.size() will return 1. However, if you added elements without creating the array first things will be different:
HashMap<int[], Integer> map2 = new HashMap<>();
map2.put(new int[]{4,5,6}, 6);
map2.put(new int[]{4,5,6}, 6);
map2.put(new int[]{4,5,6}, 6);
This way, the HashMap will add all the three new elements so the map2.size() will return 3 and not 1 as expected.
The explanation is that with the first map I created the object arr once and tried to add the same object 3 times which HashMap does not allow by default so only the last usage will be considered. With the second map, however, evey time I recreate a new object on the stack. The three objects created are different and separated thought the three of them have the same data but they are different. That's why HashMap allowed them as different keys.
Bottom line, you don't need to prevent HashMap from adding dublicated keys because it won't by design. However, you have to watch out how you define these keys because the fault may be on your side.
List<String> keys = new ArrayList<String>(); (1000000)
List<String> values = new ArrayList<String>(); (1000000)
Map<String, String> map = new HashMap<String, String>();
int i =0;
for(String key : keys){
String returnedValue = map.put(key, values.get(i));
if(returnedValue!=null){
map.put(key, returnedValue);
system.out.println("Duplicate key trying to be entered with new value so reverting the duplicate key ="+key+"new Value"+values.get(i));
}
}
Unfortunately, it is the way that Map works.
The easiest workaround is to remove all pre existed keys and their values by calling hm.remove() first! like this:
for (String name : names) {
hm.remove(name);
hm.put(name,uri.getQueryParameter(name));
}
And if you don't use a for loop just call it like this:
hm.remove("John");
hm.put("John","1");
hm.remove("Alex");
hm.put("Alex","2");
hm.remove("Mike");
hm.put("Mike","3");
And so on ...
see even if u write same key values multiple times you will just have unique set of pairs. Check that by either iterating or by doing hm.size();
if(hm.put("John","1") != null)
{
// "John" was already a key in the map. The sole value for this key is now "1".
}
List<Object> yourElements = new ... // 10000000
for(Object O : yourElements) {
if(myMap.get(O.key)==null) {
myMap.put(O.key,O);
}
}

Categories