Java HashMap, get(key) method doesnt work - java

I'm trying to create a PhoneBook class that uses a HashMap in Java. When I add an entry using the put() method in addContact(), it works fine, but when I try to retrieve values in the searchContact() method, none are returned. I'm not getting null values; HashMap definitely contains the key(s) I am searching for, but the values associated with the key(s) are not being returned. Thank you in advance.
Here is my code:
public class PhoneBookContactsImpl {
private Map<String, List<String>> contactMap = new HashMap<String, List<String>>();
public void addContact(String name, List<String> list) {
contactMap.put(name, list);
//its working fine here
System.out.println(contactMap.get(name));
}
public Map<String, List<String>> getContactMap() {
Set set = contactMap.entrySet();
Iterator i = contactMap.entrySet().iterator();
while (i.hasNext()) {
Map.Entry me = (Map.Entry) i.next();
System.out.println(me.getKey() + " : ");
List<String> nos = (List<String>) me.getValue();
System.out.println("Nos = " + nos + " n ");
System.out.println(nos.size());
}
return contactMap;
}
public List<String> searchContact(String name) throws NoDataFoundException {
if (contactMap.isEmpty()) {
System.out.println("Empty PhoneBook");
throw new NoDataFoundException();
} else {
if (contactMap.containsValue(name))
return contactMap.get(name);
//it doesnt retrieve valur from here
else {
System.out.println("No Entry for Specified Entry");
throw new NoDataFoundException();
}
}
}
}

your if statement is checking if the phonebook has name as a value, so your get is never reached.
Try this:
if (contactMap.containsKey(name))
return contactMap.get(name);

As the other answer points out you should be checking containsKey because name is a key, not a value. But why not make the whole thing much easier:
public List<String> searchContact(String name) throws NoDataFoundException {
List<String> result = contactMap.get(name);
if (result == null) {
// empty map, or no matching value or value is null
throw new NoDataFoundException();
}
}

You are doing:
if (contactMap.containsValue(name))
return contactMap.get(name);
and you need to do:
if (contactMap.containsKey(name))
return contactMap.get(name);

Related

Java stream groupingby nested string

I have a list of string, and I want to be able to group them hierarchically.
Example of the list:
var list = new String[]{"caso.id",
"caso.unidadeDoCaso.id",
"caso.etiqueta",
"caso.sigiloso",
"caso.idPecaSegredoJustica",
"caso.numeroAno",
"caso.numero",
"caso.competencia.id",
"caso.competencia.ativo",
"caso.competencia.nome",
"caso.responsavel.id",
"caso.responsavel.dadosPessoais.nome",
"caso.escrivao.id",
"caso.escrivao.dadosPessoais.nome"};
I want to group them in Maps.
Like:
caso->
id
sigiloso,
...
unidadeDoCaso->
id
competencia->
id
ativo
...
responsavel->
id
dadosPessoais->
nome
...
...
...
I was able to group just one level. I was wondering if there's a way to do it recursively.
In spite of my suggestion I decided to provide this. There are two recursive routines.
one to fill the map.
the other to print it.
String[] array = {
"caso.id","caso.unidadeDoCaso.id","caso.etiqueta",
"caso.sigiloso","caso.idPecaSegredoJustica","caso.numeroAno",
"caso.numero","caso.competencia.id","caso.competencia.ativo",
"caso.competencia.nome","caso.responsavel.id",
"caso.responsavel.dadosPessoais.nome","caso.escrivao.id",
"caso.escrivao.dadosPessoais.nome"
};
Create the map
Then iterated across the data, splitting on the dot.
then call fill with the map, just split nodes, and the starting node index.
Map<String, Object> map = new HashMap<>();
for (String s : array) {
String[] nodes = s.split("\\.");
fill(map, nodes, 0);
}
print(map, "");
prints
caso
unidadeDoCaso
id
etiqueta
idPecaSegredoJustica
escrivao
id
dadosPessoais
nome
sigiloso
numero
id
numeroAno
responsavel
id
dadosPessoais
nome
competencia
ativo
nome
id
The fill method continues until the supplied nodes are all processed.
first the map is checked to see if the node exists or not(equal to null)
if not present, a new map is constructed and added to the supplied map. Then the method is called to process the next node.
otherwise, the method is called to add the current node to the map after the one that exists and continue processing the nodes.
public static void fill(Map<String, Object> map, String[] nodes, int i) {
if (i >= nodes.length) {
return;
}
String node = nodes[i];
#SuppressWarnings("unchecked")
Map<String, Object> obj = (Map<String, Object>)(node);
if (obj == null) {
Map<String, Object> m = new HashMap<>();
map.put(node, m);
fill(m, nodes, i + 1);
} else {
fill( obj, nodes, i + 1);
}
}
This prints the map elements and indents each subsequent nested map level on a separate line.
#SuppressWarnings("unchecked")
public static void print(Map<String, Object> map, String indent) {
for (String key : map.keySet()) {
if (key != null) {
System.out.println(indent + key);
print((Map<String, Object>) map.get(key), indent + " ");
}
}
}
Here is how you could do this using a Map<String, Map> and mutable reduction using the collect method that takes a supplier, accumulator, and combiner. The API is not the most pleasant to use, as WJS pointed out.
It requires unchecked casts because you can't represent these recursive structures of unknown depth using generics.
class Scratch {
public static void main(String[] args) {
var list = new String[]{"caso.id",
"caso.unidadeDoCaso.id",
"caso.etiqueta",
"caso.sigiloso",
"caso.idPecaSegredoJustica",
"caso.numeroAno",
"caso.numero",
"caso.competencia.id",
"caso.competencia.ativo",
"caso.competencia.nome",
"caso.responsavel.id",
"caso.responsavel.dadosPessoais.nome",
"caso.escrivao.id",
"caso.escrivao.dadosPessoais.nome"};
Map<String, Map> result = Arrays.stream(list).collect(HashMap::new, Scratch::mapRecursively, HashMap::putAll);
System.out.println(result);
// {caso={unidadeDoCaso={id=null}, etiqueta=null, idPecaSegredoJustica=null, escrivao={id=null, dadosPessoais={nome=null}}, sigiloso=null, numero=null, id=null, numeroAno=null, responsavel={id=null, dadosPessoais={nome=null}}, competencia={ativo=null, nome=null, id=null}}}
System.out.println(result.get("caso").keySet());
// [unidadeDoCaso, etiqueta, idPecaSegredoJustica, escrivao, sigiloso, numero, id, numeroAno, responsavel, competencia]
}
#SuppressWarnings("unchecked")
private static void mapRecursively(HashMap<String, Map> map, String s) {
// first recursion: s = caso.competencia.id
// second recursion: s = id
int dot = s.indexOf('.');
// Base case 1
if (dot == -1) {
map.put(s, null);
return;
}
String key = s.substring(0, dot); // caso
String value = s.substring(dot + 1); // competencia.id
boolean isFirstTimeToComeAcrossWord = !map.containsKey(key);
if (isFirstTimeToComeAcrossWord) {
map.put(key, new HashMap<>());
}
// Base case 2
int dot2 = value.indexOf('.');
if (dot2 == -1) {
map.get(key).put(value, null);
return;
}
String newKey = value.substring(0, dot2); // competencia
String leftover = value.substring(dot2 + 1); // id
boolean isFirstTimeWeComeAcrossNestedWord = !map.get(key).containsKey(newKey);
// Recursive cases
if (isFirstTimeWeComeAcrossNestedWord) {
var newMap = new HashMap<String, Map>();
map.get(key).put(newKey, newMap);
mapRecursively(newMap, leftover);
} else {
mapRecursively((HashMap<String, Map>) map.get(key).get(newKey), leftover);
}
}
}

edit hashmap with hashset as value

I have the following code:
HashMap<String, HashSet<Person>> index = new HashMap<String, HashSet<Person>>();
public static void indexDB(String base)
{
for(Person i: listB)
{
if(name.equals(base))
{
}
}
listB is an array with Person elements.
So, if a Person's name matches the String base, they are getting attached to a pair of key-value in the index HashMap. The HashSet for each key contains the Persons that their name matches the String base. How can this be done?
Also, I have a method like:
public void printPersons(String sth)
{
}
that I want it to print the persons contained in the HashSet of the key called each time.
Thank you
Use putIfAbsent to insert an empty hash set place holder.
Then add new person to existing set:
HashMap<String, HashSet<Person>> index = new HashMap<String, HashSet<Person>>();
public static void indexDB(String base)
{
for(Person i: listB)
{
if(name.equals(base))
{
index.putIfAbsent(base, new HashSet<>());
index.get(base).add(i)
}
}
Note: In order to correctly add person to set, you have to implement equals()/hashCode() for your Person class, since Set use equals() to determine uniqueness
Instead of creating HashSet object in every iteration, create it only when name matches like in the below code -
public static void indexDB(String base)
{
for(Person i: listB)
{
if(index.containsKey(base)){
HashSet<Person> existingHS = index.get(base);
existingHS.add(i);
index.put(base,existingHS);
}else{
HashSet<Person> hs = new HashSet<Person>();
hs.add(i);
index.put(base,hs);
}
}
Do this
HashMap<String, HashSet<Person>> index = new HashMap<String, HashSet<Person>>();
public static void indexDB(String base)
{
HashSet<Person> h = new HashSet<String>();
for(Person i: listB)
{
//I assume it is i.name here
if(i.name.equals(base))
{
h.add(i);
}
}
index.put(base,h);
}
And for printing, do this
public void printPersons(String sth)
{
Map mp = index.get(sth);
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
}
}

Iterate Map in Java

Entry which needs to compare with the List and get the value from Map which is not there is the List.
for (Map.Entry<String, Object> entry : itemObj.entrySet())
{
System.out.println(entry.getKey());
for (ItemProcessVO processVO : itemDetails2){
if (entry.getKey().equalsIgnoreCase(processVO.getAccount())){
String account = processVO.getAccount();
lstAccVO.add(account);
}
}
}
This is the code i have used.I have Map of entry.getKey() has 6 Values while itemDetail2 has only 5 elements.I need to display only the missing account after comparing.
Simply add an else-statement to your if clause that stores that account in a local variable. Then after your for loops you can do whatever with that.
Hint: you can use loop over Map#keySet() instead of Map#entrySet() and bypass the entries that way.
In the provided example you compared the key with the account, simply use the else- statement to find the missingAccounts to iterate after this loop over them.
List<ItemProcessVO> missingAccounts= new ArrayList<>();
for (Map.Entry<String, Object> entry : itemObj.entrySet())
{
System.out.println(entry.getKey());
for (ItemProcessVO processVO : itemDetails2){
if (entry.getKey().equalsIgnoreCase(processVO.getAccount())){
String account = processVO.getAccount();
lstAccVO.add(account);
}else{
missingAccounts.add(account)
}
}
}
Below code should do the trick. It uses case insensitive comparison and prints remaining keys in the end, more explanation is in comments:
public static void main(String[] args) throws IOException {
Map<String, Object> itemObj = new HashMap<>(); //Your Map
List<ItemProcessVO> itemDetails2 = new ArrayList<>();// Your list
//First, get all the keys of the map
Set<String> keys = new HashSet<>(itemObj.keySet());
//Now, iterate through list and remove the matching items
for(ItemProcessVO processVO : itemDetails2){
String key = pop(keys, processVO.getAccount());
//If key is not null then remove it
if(null != key){
keys.remove(key);
}
}
//Now, iterate through remaining keys and print the values
for(String key : keys){
System.out.println("Missing value " + itemObj.get(key));
}
}
private static String pop(Set<String> set, String key){
if(null == set){
return null;
}else{
for(String element : set){
if(element.equalsIgnoreCase(key)){
return element;
}
}
}
}

Returning HashMap values and keys through an array method

I'm trying to return keys and values through an array method.
I have done this:
public ArrayList<String> translationList() {
for (String key : translations.keySet()) {
System.out.println(key + " = ");
}
return new ArrayList<String>(this.translations.values());
}
And in my Main.java
ArrayList<String> translations = dictionary.translationList();
for (String translation : translations) {
System.out.println(translation);
}
It returns
apina =
cembalo =
banaani =
monkey
harpsichord
banana
I'm not sure how to get them to print on the same line after the translation of the word. I know it's printing the for loop before returning the array but that is where my problem is and not sure how to solve it.
Since you are getting only values back there is no way to get key based on value. So hence not possible.
What you can do is return keys from method and iterate that in your method.
or simply change your method to
public ArrayList<String> translationList() {
List<String> returnList = new ArrayList<>(String);
for (Entry<Integer, String> entry : testMap.entrySet()) {
returnList.add(entry.getKey()+"="+entry.getValue());
}
return returnList;
}
and in your main method
ArrayList<String> translations = dictionary.translationList();
for (String translation : translations) {
System.out.println(translation);
}

Java compare compare value of hashmap with arraylist

I'm really stucked on this problem. I'm not sure if this logic is possible, is there any other whay to achieve what I want?
I'm creating a HashMap like this.
List<String> data1 = new ArrayList();
data1.add("valid1");
data1.add("valid2");
List<String> data2 = new ArrayList();
data2.add("valid3");
data2.add("valid4");
Map<String,ArrayList> hashList = new HashMap();
hashList.put("one",data1);
hashList.put("two",data2);
So the Output will be like this:
{one=[valid1,valid2], two=[valid3,valid4]}
But what am I doing is, i'm reading a file and compare it to hashmap
Code:
String line;
String[] token;
try {
LineIterator it = FileUtils.lineIterator(file,"UTF-8");
while(it.hasNext()){
line = it.nextLine();
token = StringUtils.split(line,(","));
if(token[1].equalsIgnoreCase( //check if its equal to the value of the hashmap){
System.out.println("Valid");
}
}
}
my file looks like this :
test1,valid1,check1
test2,valid3,check2
So what I want to do is, to check if the "token[1]" is valid to the value of hashmap.
Thank you in advance!
Convert the map to list
List<String> list = new ArrayList<String>(map.values());
Then use
list.contains(token[1])
to check if its equal to the list content which is the value of the hashmap
ArrayList<String> check;
check = your_hash_map.get(token[1]);
if(check != null){System.out.println("Valid");}
If you want to get the valid key for the token, the most expensive way of achieving your goal is iterating over the hash keys than iterating over the array value for that key and check if any string inside it matches your conditional.
It should looks like this:
String getValidKey(String token, Map<String, List<String>> hashList) {
for (String key: hashList.keySet()) {
for (String valid: hashList.get(key)) {
if (valid.equalsIgnoreCase(token)) {
return key;
}
}
}
return null;
}
If you only need to know if the token is valid or not this should be enough:
boolean isValid(String token, Map<String, List<String>> hashList) {
for (List<String> list: hashList.values()) {
for (String valid: list) {
if (valid.equalsIgnoreCase(token)) {
return true;
}
}
}
return false;
}

Categories

Resources