Hashmap overwrites values. How to add multiple of the same key? - java

I know hashMap overwrites the kay, but I really need the same key to be provided for another value. What is also the issue is that in the postRequest further down, it needs to be set as a Map value.
So how can the below be fixed so that the body contains all the field and their values below as displayed in the table?
So we can't have field3 = tree, cone, it has to be field 3 = tree, field 3 = cone or the service will fail.
Example step:
|field |value |
|----------|--------------------------------------------|
|field1 |shop |
|field2 |apple |
|field3 |tree |
|field3 |cone |
#Step("Example step: <table>")
public void exampleStep(Table table) {
Map<String, Object> body = new HashMap<>();
table.getTableRows().forEach(row -> {
String value = row.getCell(VALUE);
String field = row.getCell(FIELD);
body.put(field, value);
});
final String url = String.format("%s/service/%s", System.getenv(ENDPOINT), service);
new DBrequest(dataStore, url, HttpMethod.POST).postRequest(body);

If you have a Map<String, List<String>> for example, you have to check if keys are present when you are inputting values, see this:
#Step("Example step: <table>")
public void exampleStep(Table table) {
table.getTableRows().forEach(row -> {
String value = row.getCell(VALUE);
String field = row.getCell(FIELD);
// you have to check if the key is already present
if (body.containsKey(field)) {
// if it is, you can simply add the new value to the present ones
body.get(field).add(value);
} else {
// otherwise you have to create a new list
List<String> values = new ArrayList<>();
// add the value to it
values.add(value);
// and then add the list of values along with the key to the map
body.put(field, values);
}
});
}
You can iterate such a Map in several ways, one is this:
for (Entry<String, List<String>> entry : body.entrySet()) {
// print the key first
System.out.println(entry.getKey() + ":");
// then iterate the value (which is a list)
for (String value : entry.getValue()) {
// and print each value of that list
System.out.println("\t" + value);
}
};
}
Please note:
This is a simple example without any content and it doesn't handle any casting from Object.

Related

How to print a single Key-Value pair in a HashMap in java?

Is it possible to do so? If yes, what is the required syntax/method?
I tried it by using,
System.out.println(key+"="+HM.get(key));
but it prints it in this format,
key= value
whereas, I need
key=value
(Due to outputting format in HackerRank)
while(sc.hasNextLine())
{
String s=sc.nextLine();
if(a.containsKey(s))
{
System.out.println(s+"="+a.get(s));
}
else
System.out.println("Not found");
}
EDIT 1:
I saw the solution given, the person used the following code,
while(scan.hasNext()){
String s = scan.next();
Integer phoneNumber = phoneBook.get(s);
System.out.println(
(phoneNumber != null)
? s + "=" + phoneNumber
: "Not found"
);
}
Now, why does this not have white space in the answer?
The only visible change I see is that this person used an object instead of primitive data type.
Also,this person used int instead of string in accepting the phone number, I initially did the same but it gave me an InputMismatchException .
There is no avalilable method in https://docs.oracle.com/javase/7/docs/api/java/util/Map.html to get Entity from map if there is any key or value available. Try below code if it help :
if (map.containsKey(key)) {
Object value = map.get(key);
System.out.println("Key : " + key +" value :"+ value);
}
You can use entrySet() (see entrySet) to iterate over your map.
You will then have access to a Map Entry which contains the methods getValue() and getKey() to retreive both the value and the key of your mapped object.
entrySet() returns a Set, and Set extends Collection, which offers the stream() method, so you can use stream to loop over and process your entrySet :
map
.entrySet() // get a Set of Entries of your map
.stream() // get Set as Stream
.forEach( // loop over Set
entry -> // lambda as looping over set entries implicitly returns an Entry
System.out.println(
entry.getKey() // get the key
+ "="
+ entry.getValue() // get the value
);
If needed, you can add .filter() to process only elements that matches your conditions in your Stream.
Working example here
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, String> myMap = new HashMap<String, String>() {
private static final long serialVersionUID = 1L;
{
for (int i = 1 ; i < 10 ; i++) {
put("key"+i, "value"+i);
}
}
};
myMap.entrySet().stream().forEach(
entry -> System.out.println(entry.getKey() + "=" + entry.getValue())
);
}
}
Output :
key1=value1
key2=value2
key5=value5
key6=value6
key3=value3
key4=value4
key9=value9
key7=value7
key8=value8

Java 8 Streams hashmap

I need perform an hashmap iteration using Java 8 streams. I need to iterate over an hashmap. Check whether a particular key ("new") does not have null or empty values, copy that value to a variable (String val1) of type string. Then again check for another key for ex:"old" and then copy that value to a variable (String val2) of type string and call the main method where i need to send these 2 values (val1, val2). This has to be done with in hashmap iteration. Can you please help me on this.
The code:
map1.entrySet()
.stream()
.filter(s -> {
if (s.getKey().contains("abc") && !s.getValue().equals("") && s.getValue()!=null) {
String val1 = s.getValue;
if (s.getKey().contains("bb")) {
String val2 = s.getValue(); //call the function
callFunction(val1,val2);
}
}
else {
}
});
Need to be done using Java 8
for(Map.Entry e : map1.entrySet()) {
if(e.containsKey("new")&& !e.getValue().equals("")){
String val1 = (String) e.getValue();
if(e.containsKey("old")&& !e.getValue().equals("")){
String val2 = (String) e.getValue();
//call the function-- This is boolean
if(validateMethod(val1, val2)){ // if true
Map<String, String> map2 = new HashMap<>();
map2.putAll(e);
}
}
}
}
You need to look for particular keys : new and old so you don't need to iterate over the entries of the map, because if the keys exist they will be unique.
get the value of the specific keys, if they don't exist, keep en empty String
do your stuff with these values
Map<String, String> map1 = ...;
String v1 = map1.getOrDefault("new", "");
String v2 = map1.getOrDefault("old", "");
Map<String, String> map2 = new HashMap<>();
if(!v1.isEmpty() && !v2.isEmpty() && validateMethod(v1, v2)){
// do your stuff
}
You might put the check for isEmpty in your validateMethod rather than in an if
Try it with this:
yourMap.entrySet().stream()
From this point, you can manage. Stream consists of Entry<Key,Value> so you can check whatever you want to.

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

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.

Update the content of Properties instance

I have an instance of Properties, named props. The key-value contents are as follows:
"a" : "apple"
"c" : "orange"
"b.1" : "tea"
"b.2" : "coffee"
"b.3" : "coke"
...
(Each key is unique.)
What I want to achieve is:
I am only interested in keys b.<number>, I need b.1 has value water.
if there is a value water but is not with key b.1, instead, with key b.<x>, then, I swap the value of b.1 & b.<x>.
If there isn't a value water, I increase the number part of key b.<number> by 1, after which I insert "b.1" : "water" in the Properties instance.
I started to implement it with this code:
// initialize a HashMap
Map<String, String> propMap = new HashMap<String, String>();
// check what are the property key-values
Set<Object> keySet = props.keySet();
for (Object key : keySet) {
String keyStr = (String) key;
String valueStr = props.getProperty(key);
if (keyStr.startsWith("b.")) {
// if it is not value "water"
if (!valueStr.equals("water")) {
// I get lost...
}
}
}
I am not sure how to implement this in an efficient way without looping through the properties multiple times...
I don't readily see a way to do this without iterating twice (or in the case below, copying to a new Properties object), but the code below will work. Also, I create another Properties object only when water is not found, so it may not be terrible depending on your use case.
private static Properties setUpProperties() {
Properties props = new Properties();
props.setProperty("a", "apple");
props.setProperty("c", "orange");
props.setProperty("b.1", "tea");
props.setProperty("b.2", "coffee");
props.setProperty("b.3", "coke");
return props;
}
#Test
public void testProperties() {
#SuppressWarnings("unchecked")
Map<String, String> sortedMap = new TreeMap(updateContents()); //just for logging
System.out.print("Properties=" + sortedMap);
}
public static Properties updateContents() {
// initialize a HashMap
Properties props = setUpProperties();
#SuppressWarnings("unchecked")
Map<String, String> sortedMap = new TreeMap(props); //just for logging
System.out.print("Properties="+sortedMap+"\n");
// check what are the property key-values
boolean foundWater = false;
for (String key : props.stringPropertyNames()) {
if (key.startsWith("b.")) { //only b keys
String value = props.getProperty(key);
if ("water".equals(value)) {
foundWater = true;
if ("b.1".equals(key)) {
return props;
}
else {
//swap b.1 value with b.x value
int digit = getDigit(key);
props.setProperty("b." + digit, props.getProperty("b.1"));
props.setProperty("b.1", "water");
}
}
}
}
if (foundWater) {
return props;
}
else {
Properties propertiesCopy = new Properties(); //avoid a ConcurrentModificationException
propertiesCopy.putAll(props);
for (String key : propertiesCopy.stringPropertyNames()) {
//increment all other b-values by one
if (key.startsWith("b.")) {
int digit = getDigit(key);
int incremented = digit + 1;
propertiesCopy.setProperty("b." + incremented, propertiesCopy.getProperty(key));
}
}
propertiesCopy.setProperty("b.1", "water");
return propertiesCopy;
}
}
/**
* Returns the digit given a key from a Properties object (this is x)
*/
private static int getDigit(String key) {
String digit = key.substring(key.lastIndexOf(".") + 1); //use period as delimiter
return Integer.valueOf(digit);
}
You could also put in equalsIgnoreCase checks instead.

Selecting best data structure

Name - Code (String)
A - 123
B - 123
C - 23
D - 123
E - 23
F - 23
G - 66
H - 66
What's the best data structure to represent this data. Names should be able to iterate easily.
Edit
Names are unique.
What's needed to be done is something like this.
Had doubts in using Hashmap that why I asked.
Code is a STRING
for( loop dataStructure names (lets say n)){
if(NAME.equals(n){
String code = dataStructure.get(n);
do somthing
}
}
If the names are unique, a HashMap woulrd be apropriate.
You can iterate over the keys with keys().
To iterate over the entries you can iterate over the entrySet().
See the JavaDoc of Map
If you need to perform a reverse lookup you could use the BiMap from Guava. (General a very good library)
Map entries example:
public final class MapExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("A", "123");
for (Map.Entry<String, String> mapEntry : map.entrySet()) {
if (mapEntry.getKey().equals("A")) {
final String code = mapEntry.getValue();
System.out.println("Your desired code: " + code);
}
}
}
}
But since NAME seems to be a constant, you could simple do String code = map.get(NAME)?
I thinks you are considering this:
public enum Code {
A("123"),
B("123"),
C("23"),
D("123"),
E("23"),
F("23"),
G("66"),
H("66");
final public String value;
Code(String value) {
this.value = value;
}
}
String h = Code.H.value;
for (Code code : Code.values()) {
System.out.printf("Name %s, code %s%n", code, code.value);
}
Sounds like a Map. Specifically, if the order of the names is important, you can use a TreeMap.
You can populate it with the put method, and then iterate over the entries (or just the keys, or just the values):
// Fill the map:
Map<String, String> map = new TreeMap<>();
map.put("A", "123");
map.put("B", "123");
// etc...
// Iterate over it:
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.pritnln ("Key: " + entry.getKey() + " value: " + entry.getValue());
}
EDIT:
If the order is not important, as noted in later edits to the OP, a HashMap would do just fine.
Note, however, that if you're looking for a specific key, like stated in the example in the OP, there's no point in looping over the keys - you just need to use get or containsKey:
String name = ...;
String code = map.get(name);
if (code != null) {
// do something...
}
I would suggest go for HashMap
The HashMap class uses a hashtable to implement the Map interface.
This allows the execution time of basic operations, such as get( )
and put( ), to remain constant even for large sets
HashMap are efficient for locating a value based on a key and
inserting and deleting values based on a key. The entries of a
HashMap are not ordered.
import java.util.HashMap;
import java.util.Set;
public class MyHashMapRead {
public static void main(String a[]){
HashMap<String, Integer> hm = new HashMap<String, Integer>();
//add key-value pair to hashmap
hm.put("A", "1");
hm.put("B", "2");
hm.put("C","3");
System.out.println(hm);
Set<String> keys = hm.keySet();
for(String key: keys){
System.out.println("Value of "+key+" is: "+hm.get(key));
}
}
}

Categories