Finding amount of certain item in the hashmap in Java - java

I have a method, which I use to count the items in a hashmap:
public void getAvailable(final Item item) {
System.out.println("\n" + "Item's \"" + item.getItemName() + "\" stock");
System.out.println("Name\tPrice\tAmount");
for (Map.Entry<Item, Integer> entry : stockItems.entrySet()) {
System.out.println(entry.getKey() + "\t" + entry.getValue());
}
}
But if I have specified the key item, how can I find the amount of all the items with that key in the hashmap? At the moment it returns me all the items with different keys.

Would the following acheive what you're after?
public int getAvailable(final Item item) {
int count = 0;
String itemName = item.getItemName();
for (Map.Entry<Item, Integer> entry : stockItems.entrySet()) {
Item i = entry.getKey();
if(itemName.equals(i.getItemName())) {
count += entry.getValue();
}
}
return count;
}
EDIT: edited count to start at 0

how can I find the amount of all the items with that key in the hashmap?
Hash Map key is unique value. You will have only one value for any key.

I have to guess what you're trying to achieve so I assume the following:
your map keys are instances of Item
you only have the key item and want to find the corresponding entry in the map
What you could do is:
use a separate map to the the Item instance for the key and use it to access the counts map
create a "dummy" (lookup) item which only gets the data which is used in the equals() and hashCode methods and use that to access the counts map
Example for 1.:
Map<String, Item> items = ...;
Integer quantity = stockItems.get(items.get("item"));
Example for 2.:
class Item {
private String key;
public Item(String key) {
this.key = key;
}
...
//equals() and hashCode() should only use the key field
}
Integer quantity = stockItems.get( new Item("item") );
Update:
If the key is not the only attribute of an item, you'd have to iterate over all entries in the map, check the item's key for a match and create the sum yourself.

a key is unique in a hashmap. so there can be only one value with your speicified key.

Related

Removing Keys from hashmap thru composite key value

Hey guys currently have problem with regards to removing duplicates from hashmap.
Some background:
My hashmap is in this format Map<CompositeKeyBean,ValueBean>.
CompositeKeyBean is in the form (String ID, String hashvalue);
ValueBean is an object.
So if i have a hashmap with values as such:
(ID:1,HashValue:123),Obj1
(ID:1,HashValue:234),Obj1
(ID:1,HashValue:345),Obj1
I need to remove the duplicate keys and only have items with unique IDs. currently I have come up with this, But it does not seem to work, im pretty sure i am doing something wrong.
for (Map.Entry<CompositeKeyBean, ReportDataBean> entry : list.entrySet())
{
String idvalue = entry.getKey().getCompositeKeyList().get(0);
for(int i = 1; i < list.size();i++)
{
if(list.keySet().contains(idvalue))
{
list.remove(i);
}
}
}
My solution for this one would be to declare first an another Map which will be used to hold the number of times that a certain key has appeared in the original Map. For the second time, you can iterate the same map entrySet and remove the duplicates using the declared additional Map as reference.
Map<String, Integer> numberOfInstanceMap = new HashMap<String, Integer>(); //temporary placeholder
for (Map.Entry<CompositeKeyBean, ReportDataBean> entry : list.entrySet())
{
String idvalue = entry.getKey().getCompositeKeyList().get(0);
if(!numberOfInstanceMap.containsKey(idvalue)) {
numberOfInstanceMap.put(idvalue, 1); //initialize the key to 1
} else {
numberOfInstanceMap.replace(idValue, numberOfInstanceMap.get(idValue) + 1); //add 1 to the existing value of the key
}
}
for (Map.Entry<CompositeKeyBean, ReportDataBean> entry : list.entrySet())
{
String idvalue = entry.getKey().getCompositeKeyList().get(0);
Integer i = numberOfInstanceMap.get(idValue);
if(i>1) { //remove duplicate if the key exists more than once
list.remove(idValue);
}
}
If you are expecting duplicate keys, then you can do the following way to handle it while populating the map itself:
Map<String, String> map = new HashMap<>();
if(map.containsKey("ID")){
String oldValue = map.get("ID");
//put logic to merge the value
}else{
map.put("ID","newValue");
}

Compare value according to key in LinkedHashMap to another LinkedHashMap using java

I have two linked hashmap (key - String, value = String[]) which got the same size and the same keys in both linked hashmaps, I want to be able to compare values according to the key, verifying values on one linked hashmap are equals to the same values in the second linked hashmap (by key) or at least the other linked hashmap contains the values.
I am populating both of the linked hashmaps with keys and values and set it to different linked hash maps.
Example for hashmap:
Key - alert - Value (array of strings)
0 - Device_UID,Instance_UID,Configuration_Set_ID,Alert_UID
1 - a4daeccb-0115-430c-b516-ab7edf314d35,0a7938aa-9a01-437f-88ac-4b2927ed7665,96,61b68069-9de7-4b85-83cb-8d9f558e8ecb
2 - a4daeccb-0115-430c-b516-ab7edf314d35,0a7938aa-9a01-437f-88ac-4b2927ed7665,12,92757faa-bf6b-4aa3-ba6d-2e57b44f333c
3 - a4daeccb-0115-430c-b516-ab7edf314d35,0a7938aa-9a01-437f-88ac-4b2927ed7665,369,779b3294-2ca3-4613-a413-bf8d4aa05d16
and it should be at least in the second linked hash- map
String rdsColumns="";
for(String key : mapServer.keySet()){
String[] value = mapServer.get(key);
String[] item = value[0].split(",");
rdsColumns="";
for(String val:item){
rdsColumns = rdsColumns.concat(val + ",");
}
rdsColumns = rdsColumns.concat(" ");
rdsColumns = rdsColumns.replace(", ", "");
info(("Query is: "+ returnSuitableQueryString(rdsColumns, key, alertId, deviceId)));
String query=returnSuitableQueryString(rdsColumns, key, alertId, deviceId);
mapRDS.put(key, insightSQL.returnResultsAsArray(query ,rdsColumns.split(","),rdsColumns));
}
where rdsColumns are the fields I am querying in RDS data-base.
Expected: iterating over both maps and verifying at that all values according to key in the first map contains or equal in the second map.
This is the code you are looking for:
for (String keys : firstMap.keySet()) {
String[] val1 = firstMap.get(keys);
String[] val2 = secondMap.get(keys);
if (Arrays.equals(val1, val2)) {
//return true;
}
ArrayList<Boolean> contains = new ArrayList<>();
for (int i = 0; i < val1.length; i++) {
for (String[] secondMapVal : secondMap.values()) {
List<String> list = Arrays.asList(secondMapVal);
if (list.contains(val1[i])) {
contains.add(true);
break;
} else contains.add(false);
}
}
if (contains.contains(true)) {
//return true; Even a single value matches up
} else {
//return false; Not even a sinle value matches up
}
}
Basically what we have here is a HashMap<String, String>. We take the set of keys and iterate through them. Then we take the value with the key from the two sets. After we got the values we compare them and if they are the same I just print that they match. You can change this and implement this with other types of HashMaps, even where you use custom values. If I didn't understand your problem tell me and I will edit the answer.

Contains operation in hashmap key

My hashmap contains one of entry as **key: its-site-of-origin-from-another-site##NOUN** and **value: its##ADJ site-of-origin-from-another-site##NOUN**
i want to get the value of this key on the basis of only key part of `"its-site-of-origin-from-another-site"``
If hashmap contains key like 'its-site-of-origin-from-another-site' then it should be first pick 'its' and then 'site-of-origin-from-another-sit' only not the part after '##'
No. It would be a String so it will pick up whatever after "##" as well. If you need value based on substring then you would have to iterate over the map like:
String value = map.get("its...");
if (value != null) {
//exact match for value
//use it
} else {//or use map or map which will reduce your search time but increase complexity
for (Map.Entry<String, String> entry : map.entrySet()) {
if (entry.getKey().startsWith("its...")) {
//that's the value i needed.
}
}
}
You can consider using a Patricia trie. It's a data structure like a TreeMap where the key is a String and any type of value. It's kind of optimal for storage because common string prefix between keys are shared, but the property which is interesting for your use case is that you can search for specific prefix and get a sorted view of the map entries.
Following is an example with Apache Common implementation.
import org.apache.commons.collections4.trie.PatriciaTrie;
public class TrieStuff {
public static void main(String[] args) {
// Build a Trie with String values (keys are always strings...)
PatriciaTrie<String> pat = new PatriciaTrie<>();
// put some key/value stuff with common prefixes
Random rnd = new Random();
String[] prefix = {"foo", "bar", "foobar", "fiz", "buz", "fizbuz"};
for (int i = 0; i < 100; i++) {
int r = rnd.nextInt(6);
String key = String.format("%s-%03d##whatever", prefix[r], i);
String value = String.format("%s##ADJ %03d##whatever", prefix[r], i);
pat.put(key, value);
}
// Search for all entries whose keys start with "fiz"
SortedMap<String, String> fiz = pat.prefixMap("fiz");
fiz.entrySet().stream().forEach(e -> System.out.println(e));
}
}
Prints all keys that start with "fiz" and sorted.
fiz-000##whatever
fiz-002##whatever
fiz-012##whatever
fiz-024##whatever
fiz-027##whatever
fiz-033##whatever
fiz-036##whatever
fiz-037##whatever
fiz-041##whatever
fiz-045##whatever
fiz-046##whatever
fiz-047##whatever
fizbuz-008##whatever
fizbuz-011##whatever
fizbuz-016##whatever
fizbuz-021##whatever
fizbuz-034##whatever
fizbuz-038##whatever

JAVA Iterateing through Hasmap with list

I need iterate through hashmap and get key value which should be a string and all values within that key which is a list of strings that have strings?
Psuedo code
static HashMap<String, List<String>> vertices = new HashMap<String, List<String>>();
for (int i = 0; i < vertices.size(); i++)
{
String key = vertices.getKey at first postions;
for (int x = 0; x < size of sublist of the particular key; x++)
{
String value = vertices key sublist.get value of sublist at (i);
}
}
You can't iterate over HashMap directly, as there is no numeric index of values within HashMap. Instead key values are used, in your case of type String. Therefore the values don't have a particular order. However, if you want, you can construct a set of entries and iterate over that, using vertices.entrySet().
for (Entry<String, List<String>> item : vertices.entrySet()) {
System.out.println("Vertex: " + item);
for (String subitem : item.getValue()) {
System.out.println(subitem);
}
}
Try vertices.keySet();
It gives a Set of all keys in the map. Use it in a for loop like below
for (String key : vertices.keySet()) {
for (String value : vertices.get(key)) {
//do stuff
}
}

Associate multiple values with the single key and also maintain the order of values

I have a class which contain the following members
private String patientName;
private String patientPhoneNumber;
now I have multiple names attached with the phone No. for example
1234567, AAA
1234567, BBB
8765432, CCC
8765432, GGG
Now I want to store them in a Map but the phone No. should be the key having multiple values, for 1234567 i should have value AAA and BBB, please advise how can I store the multiple values with the single key in map here my key is Phone No. and then please let me know if I want to print in console then ow would I iterate over the Map
Also please not that I want to maintain the order also let say first I get the value AAA and then BBB so i should maintain these order also, since I get this is just a example but in my scenario I will be getting this value from backend so to maintain the order is also necessary please advise.
You may try something like this:
HashMap<String,LinkedList<String>> map
private Map<String,List<String>> patients;
public void setPatientNumber(String number, String patient){
List<String> list = patients.get(number);
if(list == null){
list = new ArrayList<String>();
patients.put(number,list);
}
list.add(patient);
}
new Map<String, TreeSet<String>>()
Will allow you to store the values in a TreeSet (sorted...).
To print them:
for(Map.Entry entry : phoneBook.entries()){
System.out.println(entry.key() + ":");
TreeSet names = entry.value();
for(String name : names){
System.out.println("\t" + name);
}
}
You can add, like this, if you want case insensitive ordering:
TreeSet<String> nameSet = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
phoneBook.add(number, nameSet);
Use a LinkedHashMap and an ArrayList for each values :
LinkedHashMap<String,ArrayList<String>> phoneNumbers = new LinkedHashMap<String,ArrayList<String>>();
// register new phone number
phoneNumbers.put("1234567", new ArrayList<String>());
// add names to the phone number
phoneNumbers.get("1234567").add("AAA");
phoneNumbers.get("1234567").add("BBB");
Both collections preserve the insertion ordering.
** Edit **
Here, this is roughly what you'd need (this was done on the spot without much testing, but you should get the idea). Since your ordering may vary, I thought limiting duplicates and providing a comparator for ordering should be preferable (as suggested by other answers) :
public class LinkedMultiMap<K,V> {
private Comparator<V> comparator;
private LinkedHashMap<K,Set<V>> entries;
public LinkedMultiMap() {
this(null);
}
public LinkedMultiMap(Comparator<V> comparator) {
this.comparator = comparator;
this.entries = new LinkedHashMap<K, Set<V>>();
}
public boolean add(K key, V value) {
if (!entries.containsKey(key)) {
entries.put(key, new TreeSet<V>(comparator));
}
return entries.get(key).add(value);
}
public Collection<V> get(K key) {
return entries.get(key);
}
public boolean remove(K key, V value) {
boolean removed = false;
if (entries.containsKey(key)) {
removed = entries.get(key).remove(value);
if (entries.get(key).isEmpty()) {
entries.remove(key);
}
}
return removed;
}
public Collection<V> removeAll(K key) {
return entries.remove(key);
}
public Iterator<K> keyIterator() {
return entries.keySet().iterator();
}
}
Associate multiple values with the single key
That is a Multimap:
A collection similar to a Map, but which may associate multiple values with a single key.
LinkedHashMultimap from Google Collections seems to fit the bill:
Implementation of Multimap that does not allow duplicate key-value
entries and that returns collections whose iterators follow the
ordering in which the data was added to the multimap.
If you don't want to add the dependency, you can use a collection as value type:
Map<String /*number*/, List<String> /*names*/> numbers;
Note that the former only allows retrieval in order of insertion, if you want to be able to change it you will have to use the latter hand-rolled solution
Use a Map to store your data. The keys should be String objects and the values should be List objects. Using a List as the map entry value allows to associate multiple values with a single key. A List will also maintain the order of adding elements.
public static void main(String[] args) {
Map<Integer,List<String>> map = new HashMap<Integer,List<String>>();
//insert values into list one
List<String> list1 = new ArrayList<String>();
list1.add("AAA");
list1.add("BBB");
//insert values into list one
List<String> list2 = new ArrayList<String>();
list2.add("CCC");
list2.add("GGG");
//insert values to keys
//single key multiple values
map.put(1234567, list1);
map.put(8765432, list2);
//iterating and displaying the values
for(Map.Entry<Integer,List<String>> entry: map.entrySet() ) {
Integer key = entry.getKey();
List<String> values = entry.getValue();
System.out.println("Value of " +key+ " is " +values);
//System.out.println("Value of " +key+ " is " +values.get(0));
//System.out.println("Value of " +key+ " is " +values.get(1));
}
}

Categories

Resources