Why does my Hashmap<Boolean,String> only have two entries? - java

I used a HashMap to store a dictionary of type boolean and the indexName value. However I noticed my hashmap only goes up to 2 in size. Why is this happening and how can I fix it?
public Map<Boolean, String> findMetadata(String scanPackage) {
Map<Boolean, String> metadatas = new HashMap<>();
ClassPathScanningCandidateComponentProvider provider = createComponentScanner();
for (BeanDefinition beanDef : provider.findCandidateComponents(scanPackage)) {
try {
Class<?> cl = Class.forName(beanDef.getBeanClassName());
Indexable indexable = cl.getAnnotation(Indexable.class);
logger.info("---------------------------- " + indexable.dictionary() + " " + indexable.indexName());
if (!metadatas.containsValue(indexable.indexName())) {
metadatas.put(indexable.dictionary(), indexable.indexName());
}
} catch (ClassNotFoundException e) {
logger.error(ERROR + e);
}
}
return metadatas;
}

Just change the map declaration in this way:
Map<String, Boolean> metadatas = new HashMap<>();
and the metadata put in this way:
metadatas.put(indexable.indexName(), indexable.dictionary());
Maybe this is what you really want to do.

You are using a Map<Boolean,String> where the key are Boolean and the value String.
Now, Map doesn't supports duplicated keys.
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
So you will be limited with the key, since Boolean can only have 3 values true, false and null... and since HashMap allows null key
This implementation provides all of the optional map operations, and permits null values and the null key
Your maxmimum size will be 3.

It is obvious, you are using Boolean as a key in a hashmap.
Now for Hashmap, below is true.
1. It should have unique keys(Otherwise, It will override the existing value stored corresponding to a key).
and
2. Boolean can have two values either true or false(Can't be null),
so there are only two values in your Map.
If you Want to have a dictionary, you should modify your MAP as below.
Map<Integer, String> metadatas = new HashMap<Integer, String>();
Index: Should be some numbers, So keys are Integer.
Values should be String.

Related

Java Determine If String Starts With Key In Map

I want to determine if a given String startsWith any key in a Map.
The simple solution is to iterate through entire the keySet.
private static Map<String, String> someMap;
private static void method(String line) {
for (String key : someMap.keySet()) {
if (line.startsWith(key)) {
// do something with someMap.get(key);
}
}
}
My question is: Is there is a better data structure to handle this problem?
This can't be done directly with an HashMap: the problem is that HashMap uses an hash calculated on the key to manage its position inside the collection. So there is no way to search for a String key which starts with a specific substring since there is no correlation between two similar String values and their hashes.
But nothing is lost, if you switch to a TreeMap<String,String> the problem can be solved easily. A TreeMap is still an associative container but it stores entries by using a red-black tree in a sorted order.
This means that elements inside a TreeMap are always sorted. In addition to this it gives you some functionalities like:
Map.Entry<K,V> ceilingEntry(K key): Returns a key-value mapping associated with the least key greater than or equal to the given key, or null if there is no such key.
Map.Entry<K,V> floorEntry(K key): Returns a key-value mapping associated with the greatest key less than or equal to the given key, or null if there is no such key.
Now, not only you can search for a specific key by using a substring of its value, but you also do it in an efficient way. Mind that this works thanks to the implementation of compareTo of String class.
So your problem becomes trivial:
TreeMap<String, Object> map = new TreeMap<String, Object>();
map.put("baz", new Object());
map.put("foo", new Object());
map.put("fooz", new Object());
map.put("fo", new Object());
Map.Entry<String, Object> test = map.ceilingEntry("fo");
bool containsSubStringKey = test != null && test.getKey().startsWith("fo");
TreeMap<String, Object> map = new TreeMap<String, Object>();
map.put("baz", new Object());
map.put("foo", new Object());
map.put("fooz", new Object());
map.put("foor", new Object());
NavigableMap tempMap = list.subMap("foo", true, "fop", false);
//This will return a map of keys that start with "foo". true means inclusive and //false exclusive. "fop" is the first key that does not start with "foo"

How to print all the values for a key in HashMap in java

Map<String, String> map = new HashMap<String, String>();
map.put("1", "xyz");
map.put("1", "abc");
map.put("1", "cde");
map.put("2", "err");`
`
for the above map I want to get all the values associated with the key 1. Expected output.
Key:: 1 values are:: xyz, abc, cde
Order of the values doesn't important.
In a Map the key should always be unique. If you associate a new value to an existing key, it will overwrite the value of the existing entry.
You might need to check the interface for Map#put(K, V) method.
If the map previously contained a mapping for the key, the old value
is replaced by the specified value.
So in your case your map will always have "cde" as the value for the key "1".
Use MultiMap
MultiMap mapValue = new MultiValueMap();
mapValue.put("1", "xyz");
mapValue.put("1", "abc");
mapValue.put("1", "cde");
mapValue.put("2", "err");
System.out.println("Map : " + mapValue);
Output: Map : {2=[err], 1=[xyz, abc, cde]}
A map can not have duplicate keys.
If you want to implement what you describe in question. First you need to use multimaps
What you are doing is wrong.
Map doesn't allow duplicates.
So one key -----------> one value
If you see docs of put()
Associates the specified value with the specified key in this map (optional operation). If the map previously contained a mapping for the key, the old value is replaced by the specified value. (A map m is said to contain a mapping for a key k if and only if m.containsKey(k) would return true.)
You can print the values of each key and value like
Ex:
Map<String, String> map = new HashMap<String, String>();
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
In Map you can't have duplicate keys. so In your case final value put for key 1. "cde" will remain in Map
You can do some thing like following to achive what you are expecting
Map<String, List<String>> map = new HashMap<>();
List<String> list=new ArrayList<>();
List<String> list1=new ArrayList<>();
list.add("xyz");
list.add("abc");
list.add("cde");
list1.add("err");
map.put("1", list);
map.put("2",list1);
System.out.println(map.get("1"));
HashMap::put overrides the old value associated with the key. You have to put a List in each map entry and insert new values in the appropriate list.
From the java documentation about HashMap.put(K key, V value) method:
Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced.
So you can't do that.
This is impossible, a map is called a map because it maps one key value to a value. Multiple keys can map to the same value but not the other way around.
What you probably want is a map which maps to a List<String> instead:
final Map<String, List<String>> map = new HashMap<>();
if (map.get("1") == null) {
map.put("1", new ArrayList<String>());
}
map.get("1").add("xyz");
// ...
A helper function for adding might be convenient
public static <K, V> void add(final K key, final V value, final Map<K, List<V>> map)
{
if (map.get(key) == null) {
map.put(key, new ArrayList<V>());
}
map.get(key).add(value);
}
You can not do this with this type of Map. The key in map must be unique.
To be able to do that you should declare a map, where key is string but values are collections of Strings.
Map<String,Collection<String>> map = new HashMap<String,Collection<String>>();
The to list values from it you can do this
for(String valueOfKey : map.get("key") {
//print or something else
}
Note that to add some values to it you must first check that key is already stored and if not then fist declare a collection.
if(map.contains("key") == false) {
map.put(new ArrayList<String>());
}
map.get("key").add("value");
As this is well know design you might be interest in guava framework and Multimap
The benefit of this class is that it already has implemented the logic how to add and retrieve values from it.
You could do something like:
for (String k : map.keySet())
System.out.println(k);
This would print the keys in the HashMap, but without any guarantees on order.
You can not have duplicate key for a hash map see the below S.O for What happens for duplicate keys in HashMap

Search if specified key and value exists

I am working with hashmap datastructure in java. I have some data in which each entry(value) has a group(key). Now i am storing this data in hashmap as follows
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "value1");
map.put(1, "value2");
map.put(2, "value3");
map.put(2, "value4");
map.put(3, "value5");
map.put(3, "value6");
map.put(3, "value7");
now I want to search if entry (with key=3 and value="value6") exists in map or not. Is there any specific method to call? or is there and other way to do it?
You can not keep multiple entry against same key in a map. If your map previously contained a mapping for the key, the old value is replaced. You need
Map<Integer,List<String>> map = new HashMap<>();
^^^^^
(Diamond operator)
Where you could save List of string against same key. and you can get the value by map#get
List<String> str = map.get(3);
You can make use of Guava Multimap (API docs)
Its stores the multiple values against one key.
For your case ,
Multimap<Integer,String> myMultimap = ArrayListMultimap.create();
myMultimap .put(1, "value1");
myMultimap .put(1, "value2");
myMultimap .put(2, "value3");
myMultimap .put(2, "value4");
myMultimap .put(3, "value5");
myMultimap .put(3, "value6");
myMultimap .put(3, "value7");
This will create the data structure for you
now I want to search if entry (with key=3 and value="value6") exists
in map or not. Is there any specific method to call? or is there and
other way to do it?
For searching
use multimap#containsEntry(key,value), which return boolean result based on the result
therefore,
myMultimap.containsEntry(3,"value6")
which will return true
In broad terms: map.get(key) will retrieve either the value at this key location, or null if it doesn't exist.
Second, you're actually crushing your values. Maps only ever store one value per key. If you want to store multiple values, consider using another collection as the value, which you can add values into later.
Here's some sample code:
//Declaration - change List to Set if duplicates are annoying
Map<Integer, List<String>> map = new HashMap<>();
//Usage - if the list is empty at the key, new one up. Append the value afterwards.
Integer key = Integer.valueOf(1);
List<String> values = map.get(key);
if(key == null) {
values = new ArrayList<>();
}
values.add("word");
map.put(key, values);
Determining the existence of a value at a particular key becomes easy, too:
public boolean inMap(Map<Integer, List<String>> map, Integer key, String value) {
final List<String> values = map.get(key);
return values != null && values.contains(value);
}
Your key contains only the last value that u put() for a particular key as the values are overwritten for every key and only the last entered value is stored against the key in the Entry object.
As per your code your map contains the key value pairs in the following form:
{1=value2, 2=value4, 3=value7}
So, value6 doesnt exist any longer.
Looks like you need a set of pairs instead of map.
Set is library class. You can use HashSet for example.
Pair is not. You can use http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/tuple/Pair.html
So,
// init
Set<Pair<Integer, String>> set = new HashSet<Pair<Integer, String>>();
set.add(new Pair<Integer, String>(1, "1"));
// check
if (set.contains(new Pair<Integer, String>())) {
...
}
You can know if a key-pair value exists by getting the value of the desired key and comparing by comparing it to the value.
Example (Java 7 and above):
boolean exists(Map<K,V> map, K key, V value)
{
return map!=null && map.get(key)!=null && Objects.equals(map.get(key),value);
}
boolean existsinList(Map<K,V> map, K key, V value)
{
return map!=null && map.get(key)!=null && map.get(key).contains(value);
}
All the necessary checks have been included. One may analyze and remove or modify the conditions (eg. map!=null) to fit things as per their use-case and/or convert this function into a single condition that can fit in any control structure (if needed).
map stores only unique key and you have stored 3 as key and value6 as value then again 3 as a key and value7 as value then your map conains only 3 as a key and value7 as value value6 will be replaced

Printing key when value is found in hash table

I am trying to print the key value(s) in a hash table when the value is found or exists. This code does not seem to work.
Map<String,Integer> map = new HashMap<String, Integer>();
for(int j=0;j<al.size();j++){
Integer count = map.get(al.get(j));
map.put(al.get(j), count==null?1:count+1); //auto boxing and count
}
int max = Collections.max(map.values());
if( map.containsValue(max))
{
System.out.println(map.keySet());
}
Firstly, the values could occur multiple times - I assume you want to print all matching keys?
Secondly, hashtables basically aren't designed for lookup by value - so you have to iterate all the entries:
// Adjust types accordingly
for (Map.Entry<String, String> entry : map.entrySet()) {
if (entry.getValue().equals(targetValue)) {
System.out.println(entry.getKey());
}
}
You should change the equality check if it's possible that some of the values are null.

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