Using Integer in HashMaps - java

So I am trying to use HashMaps by specififying:
HashMap totalAtt = new HashMap<String, Integer>();
But when I try to add two of the Integers, it gives me an error saying bad operand. How can I add the integers I retrieve from this HashMap without a compiler error or warning?
Edit: Replaced some code, no longer getting compiler error, rather warning of unchecked or unsafe operations
public HashMap<String, Integer> getAttrib()
{
HashMap<String, Integer> totalAtt = new HashMap();
//Creates key values and initializes them to 0
totalAtt.put("strength", 0);
totalAtt.put("dexterity", 0);
totalAtt.put("constitution", 0);
totalAtt.put("intelligence", 0);
totalAtt.put("wisdom", 0);
totalAtt.put("charisma", 0);
HashMap<String, Integer> sAtt;
for(Sprite s: itemList)
{
//iterates through items and counts their attributes
sAtt = s.getAttrib();
totalAtt.put("strength", totalAtt.get("strength") + sAtt.get("strength"));
totalAtt.put("dexterity", totalAtt.get("dexterity") + sAtt.get("dexterity"));
totalAtt.put("constitution", totalAtt.get("constitution") + sAtt.get("constitution"));
totalAtt.put("intelligence", totalAtt.get("intelligence") + sAtt.get("intelligence"));
totalAtt.put("wisdom", totalAtt.get("wisdom") + sAtt.get("wisdom"));
totalAtt.put("charisma", totalAtt.get("charisma") + sAtt.get("charisma"));
}
return totalAtt;
}
From Sprite class:
public HashMap<String, Integer> getAttrib()
{
return attrib;
}

Change
HashMap totalAtt = new HashMap<String, Integer>();
to
HashMap<String, Integer> totalAtt = new HashMap<>();
and
HashMap sAtt
to
HashMap<String, Integer> sAtt

Related

Recursively increase the same nested map values if keys are already exists

My parentMap is look like something below.
HashMap<String, Integer>>> parentMap = {disabled={account={test1=22}, group={test2=10}}}
What I suppose to do is, if operationType=disabled and objectType=account or group etc and testName=test1 or test2 etc then I suppose to increase the count of test1 by 1.
I have to update the same map so that at the end I should get some statistic like there are 22 tests cases of objectType=account and 10 tests cases of objectType=group etc are disabled
I tried something below but it is going in infinite loop as I'm putting values in the map and iterating over it again.
private HashMap<String, HashMap<String, HashMap<String, Integer>>> countTags(String statType, String objectType,
String opType, HashMap<String, HashMap<String, HashMap<String, Integer>>> parentMap) {
if (!Util.isEmpty(parentMap)) {
//created new map to avoid infinite loop here but no luck :(
HashMap<String, HashMap<String, Integer>> objMap = new HashMap<>();
objMap.putAll(parentMap.get(statType));
Iterator<Entry<String, HashMap<String, Integer>>> it = objMap.entrySet().iterator();
while (it.hasNext()) {
Entry<String, HashMap<String, Integer>> operationEntry = it.next();
HashMap<String, Integer> operationMap = operationEntry.getValue();
Set<String> opKeySet = operationMap.keySet();
Iterator<String> opIt = opKeySet.iterator();
while (opIt.hasNext()) {
parentMap.put(statType, countTags(objectType, opType, operationMap));
}
}
} else {
parentMap.put(statType, countTags(objectType, opType, new HashMap<String, Integer>()));
}
return parentMap;
}
private HashMap<String, HashMap<String, Integer>> countTags(String objectType, String opType, HashMap<String, Integer> tagMap) {
int testRepeatCount = tagMap.get(opType) != null ? tagMap.get(opType) : 0;
tagMap.put(opType, 1 + testRepeatCount);
HashMap<String, HashMap<String, Integer>> objMap = new HashMap<>();
objMap.put(objectType, tagMap);
return objMap;
}
I found
a.compute(key, (k, v) -> v == null ? 1 : v + 1); also some suggestions here Java map.get(key) - automatically do put(key) and return if key doesn't exist? but can I get some help how optimally I should achieve my desired outcome here?
I finally get out of my own if_else mess. this is how my final method is look a like. This helped me here Java append `HashMap` values to existing HashMap if key matches
private HashMap<String, HashMap<String, HashMap<String, Integer>>> countTags(String statType, String objectType,
String opType, HashMap<String, HashMap<String, HashMap<String, Integer>>> parentMap) {
if (!Util.isEmpty(parentMap) && parentMap.containsKey(statType)) {
// if objType is present, count the tags
if (parentMap.get(statType).containsKey(objectType)) {
HashMap<String, Integer> objMap = parentMap.get(statType).get(objectType);
HashMap<String, Integer> map = countTags(objectType, opType, objMap).get(objectType);
parentMap.get(statType).get(objectType).putAll(map);
} else {
// if objType isn't present, add that objType and count the tags
HashMap<String, HashMap<String, Integer>> map = countTags(objectType, opType,
new HashMap<String, Integer>());
parentMap.get(statType).put(objectType, map.get(objectType));
}
} else {
// first time add the new tag to calculate it's object/operation wise
// distribution
parentMap.put(statType, countTags(objectType, opType, new HashMap<String, Integer>()));
}
return parentMap;
}

adding value if key is same in hashmap arraylist

I am having trouble in adding the values of hashmap arraylist if the key is same. I have an arraylist as
ArrayList<HashMap<String, Integer>> expense = new ArrayList<HashMap<String, Integer>>();
The output is as
{food = 300},
{entertainment = 100},
{food = 500}
I want to create a new hashmap arraylist
ArrayList<HashMap<String, Integer>> newExpense = new ArrayList<HashMap<String, Integer>>();
and store
{food= 800},
{entertainment = 100}
I have tried nested loop and all but it didnot work. Can anybody please help me?
you can have a simple hashmap for that...
while putting the values in hashmap, use this code..
if (map.containsKey(key))
map.put(key, map.get(key) + newValue);
else
map.put(key, newValue);
even though it is not recommended, if you still need to do that because of own reasons..
this could be the logic to get new expenses in a hashmap..
ArrayList<HashMap<String, Integer>> expense = new ArrayList<HashMap<String, Integer>>();
HashMap<String, Integer> newExpense = new HashMap<>();
for(HashMap<String, Integer> oldExpense : expense)
{
for(String key : oldExpense.keySet())
{
if (newExpense.containsKey(key))
newExpense.put(key, newExpense.get(key) + oldExpense.get(key));
else
newExpense.put(key, oldExpense.get(key));
}
}
System.out.println(newExpense.toString());

Rearrange a map in random fashion

I've a SortedMap<String, String> containing key:ID & value:Name.
Now I want to rearrange the elements of this Map in random fashion & store them in separate map.
// Get a random entry from the SortedMap.
String[] keyArr = student.keySet().toArray();
String key = keyArr[new Random().nextInt(keyArr.length)];
// Use a separate List<String> to store which key has been selected, so that they are not re-selected
But above method does not sound very efficient.
Please suggest.
Thank You
You would need to copy the entrySet into a List and shuffle it. This would give you the elements in a random order.
Now you can push those elements to a new LinkedHashMap - to preserve the random order. Something like the following:
final Map<String, Object> m = new TreeMap<>();
m.put("A", 1);
m.put("B", 1);
m.put("C", 1);
m.put("D", 1);
m.put("E", 1);
m.put("F", 1);
m.put("G", 1);
final List<Map.Entry<String, Object>> e = new ArrayList<>(m.entrySet());
Collections.shuffle(e);
final Map<String, Object> r = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : e) {
r.put(entry.getKey(), entry.getValue());
}
I'm not sure that I got your question, but you should be able to do something like
Map<String, String> result = new LinkedHashMap<>();
List keys = new ArrayList(map.keySet());
Collections.shuffle(keys);
for (Object o : keys) {
// Access keys/values in a random order
result.put(o, map.get(o));
}

Java invert map

I need create inverse map - select unique values and for them find keys.
Seems that only way is to iterate all key/value pairs, because entrySet returns set of <key,value> so value not unique?
The values in a map may not be unique. But if they are (in your case) you can do as you wrote in your question and create a generic method to convert it:
private static <V, K> Map<V, K> invert(Map<K, V> map) {
Map<V, K> inv = new HashMap<V, K>();
for (Entry<K, V> entry : map.entrySet())
inv.put(entry.getValue(), entry.getKey());
return inv;
}
Java 8:
public static <V, K> Map<V, K> invert(Map<K, V> map) {
return map.entrySet()
.stream()
.collect(Collectors.toMap(Entry::getValue, Entry::getKey));
}
Example of usage:
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("Hello", 0);
map.put("World!", 1);
Map<Integer, String> inv = invert(map);
System.out.println(inv); // outputs something like "{0=Hello, 1=World!}"
}
Side note: the put(.., ..) method will return the the "old" value for a key. If it is not null you may throw a new IllegalArgumentException("Map values must be unique") or something like that.
Take a look at Google Guava BiMap.
Example usage
Map<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
Map<String, Integer> inverted = HashBiMap.create(map).inverse();
To get an inverted form of a given map in java 8:
public static <K, V> Map<V, K> inverseMap(Map<K, V> sourceMap) {
return sourceMap.entrySet().stream().collect(
Collectors.toMap(Entry::getValue, Entry::getKey,
(a, b) -> a) //if sourceMap has duplicate values, keep only first
);
}
Example usage
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "one");
map.put(2, "two");
Map<String, Integer> inverted = inverseMap(map);
Seems that only way is to iterate all key/value pairs, because entrySet returns set of so value not unique?
It's one way at least. Here's an example:
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "one");
map.put(2, "two");
Map<String, Integer> inverted = new HashMap<String, Integer>();
for (Integer i : map.keySet())
inverted.put(map.get(i), i);
In case of non-unique values, this algorithm will map the last value found to it's key. (Since the iteration order is undefined for most maps, this should be as good as any solution.)
If you really do want to keep the first value found for each key, you could change it to
if (!inverted.containsKey(map.get(i)))
inverted.put(map.get(i), i);
I would give another approach to this problem giving an extra dimension:
duplicate values in EntrySet.
public static void main(String[] args) {
HashMap<Integer, String> s = new HashMap<Integer, String>();
s.put(1, "Value1");
s.put(2, "Value2");
s.put(3, "Value2");
s.put(4, "Value1");
/*
* swap goes here
*/
HashMap<String,List<Integer>> newMap = new HashMap<String, List<Integer>>();
for (Map.Entry<Integer, String> en : s.entrySet()) {
System.out.println(en.getKey() + " " + en.getValue());
if(newMap.containsKey(en.getValue())){
newMap.get(en.getValue()).add(en.getKey());
} else {
List<Integer> tmpList = new ArrayList<Integer>();
tmpList.add(en.getKey());
newMap.put(en.getValue(), tmpList);
}
}
for(Map.Entry<String, List<Integer>> entry: newMap.entrySet()){
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
T result will be that:
1 Value1 2 Value2 3 Value2 4 Value1 Value1 [1, 4] Value2 [2, 3]
Apache Commons Collections also provides a BidiMap interface for bi-directional maps, along with several implementations.
BidiMap JavaDoc
If your values duplicate and you need to store keys in list you can go with
val invertedMap = originalMap.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey, Collectors.toList()))
);
You have to assume that values may be identical, since the Map contract allows it.
In my opinion the best solution lies in using a wrapper. It will contain the original value, and add an id. Its hashCode() function will rely on the id, and you provide a Getter for the original value.
Code would be something like this:
public class MapKey
{
/**
* A new ID to differentiate equal values
*/
private int _id;
/**
* The original value now used as key
*/
private String _originalValue;
public MapKey(String originalValue)
{
_originalValue = originalValue;
//assuming some method for generating ids...
_id = getNextId();
}
public String getOriginalValue()
{
return _originalValue;
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + _id;
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MapKey other = (MapKey) obj;
if (_id != other._id)
return false;
return true;
}
#Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("MapKey value is ");
sb.append(_originalValue);
sb.append(" with ID number ");
sb.append(_id);
return sb.toString();
}
Inverting the map would be something like this:
public Map <MapKey, Integer> invertMap(Map <Integer, String> map)
{
Map <MapKey, Integer> invertedMap = new HashMap <MapKey, Integer>();
Iterator<Entry<Integer, String>> it = map.entrySet().iterator();
while(it.hasNext())
{
//getting the old values (to be reversed)
Entry<Integer, String> entry = it.next();
Integer oldKey = entry.getKey();
String oldValue = entry.getValue();
//creating the new MapKey
MapKey newMapKey = new MapKey(oldValue);
invertedMap.put(newMapKey, oldKey);
}
return invertedMap;
}
Printing the values something like this:
for(MapKey key : invertedMap.keySet())
{
System.out.println(key.toString() + " has a new value of " + invertedMap.get(key));
}
None of this code is tested, but I believe it's the best solution since it makes use of OO inheritance design instead of "c" style checks and allows you to display all the original keys and values.
With Guava
Multimaps.transformValues(Multimaps.index(map.entrySet(), Map.Entry::getValue),
Map.Entry::getKey)
You'll get a multimap (basically a map of lists) in return.

Find duplicate values in Java Map?

I want to display the values in a HashMap. A HashMap may have duplicate values (but not duplicate keys), but I want to display a value only once.
So I should find whether the Map has duplicate values. I know we can iterate over the Map and use the return boolean of map.containsValue(value). I want to know whether any method exists to find duplicate values in map or we should I write code myself?
A simple solution would be to compare the size of your values list with your values set.
// pseudo-code
List<T> valuesList = map.values();
Set<T> valuesSet = new HashSet<T>(map.values);
// check size of both collections; if unequal, you have duplicates
Example:
Map<Object, Object> map = new HashMap<Object, Object>();
map.put(1,2);
map.put(3,4);
map.put(2,2);
map.put(5,3);
Set<Object> uniqueValues = new HashSet<Object>(map.values());
System.out.println(uniqueValues);
Output:
[2, 3, 4]
Try out this code
private boolean hasDuplicates(Map<Integer, List<String>> datamap){
boolean status = false;
Set valueset=new HashSet(datamap.values());
if(datamap.values().size()!=valueset.size()){
status=true;
}
else{
status = false;
}
return status;
}
There is no such method provided as of jdk1.6.
One simple way you can do is
get all the values from the map in a list
put that list into a set which will remove the duplicates
Use apache commons library class's method
org.apache.commons.collections.MapUtils.invertMap(map)
and compare the size of actual map and invert map.
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("abc", 2);
map.put("def", 1);
map.put("hij", 4);
map.put("klm", 6);
map.put("nop", 2);
map.put("qrs", 2);
map.put("tuv", 6);
map.put("wxy", 8);
map.put("zab", 1);
map.put("cde", 5);
map.put("fgh", 4);
map.put("ijk", 3);
HashMap<Integer, String> duplicatMap = new HashMap<>();
Set<Entry<String, Integer>> entrySet = map.entrySet();
Iterator<Entry<String, Integer>> iterator = entrySet.iterator();
while(iterator.hasNext()) {
Entry<String, Integer> entry = iterator.next();
String key = entry.getKey();
Integer value = entry.getValue();
if(duplicatMap.containsKey(value)) {
duplicatMap.put(value, duplicatMap.get(value)+", "+key);
} else {
duplicatMap.put(value, key);
}
}
System.out.println(duplicatMap);
}
outPut: - {1=def, zab, 2=abc, qrs, nop, 3=ijk, 4=fgh, hij, 5=cde, 6=tuv, klm, 8=wxy}
if you want to modify then use again EntrySet.
try this code but this is not optimize code :
public class HashMapDulicate {
public static void main(String[] args) {
Map<String,Integer> map=new HashMap<>();
map.put("A", 1);
map.put("B", 1);
map.put("C", 3);
map.put("D", 4);
Set set=new HashSet<>();
List list=new ArrayList<>();
for(Entry<String, Integer> mapVal:map.entrySet()) {
if(!set.add(mapVal.getValue())) {
list.add(mapVal.getValue());
}else {
set.add(mapVal.getValue());
}
}
for(Entry<String, Integer> mapVal:map.entrySet()) {
if(list.contains(mapVal.getValue())){
System.out.println(mapVal.getKey() +":" + mapVal.getValue());
}
}
}
}
Map<Integer,Person> personMap01 = new HashMap<>();
personMap01.put(1,new Person(101,"Ram","Kumar"));
personMap01.put(2,new Person(103,"Raj","Kumar"));
personMap01.put(3,new Person(101,"Ravi","Ram"));
personMap01.put(4,new Person(105,"Gopi","Nath"));
personMap01.put(5,new Person(104,"Yogesh","Waran"));
personMap01.entrySet().stream().
filter(removeDuplicate(personMap01.values())).
forEach(System.out::println);
public static Predicate<Map.Entry<Integer,Person>>
removeDuplicate(Collection<Person> personCollection){
return e->Collections.frequency(personCollection,e.getValue())==1;
}

Categories