Add number in map java - java

I am creating a function that loops through a string, separates it by comma and then takes the key from the second item in the array and the value from the 1st after splitting the string.
I then want to place these values in a map. This works perfectly, however if i have two strings with the same key it doesn't add the value up it just replaces it.
For example if my string was
123,totti 100,roma, 100,totti
I would want
totti 223
roma 100
Here is my code
private void processCallLogs(String[] splitCalls) {
for (String individualCall : splitCalls) {
int duration = 0;
String[] singleCall = individualCall.split(",");
duration += DurationParser.returnDuration(singleCall[0]);
this.cost += CalculateCost.calculateCostPerCall(singleDuration);
if (totalCallDurations.containsKey(singleCall[1])) {
totalCallDurations.put(singleCall[1], singleDuration);
} else {
totalCallDurations.put(singleCall[1], duration);
}
}
}

You can replace the if with something like this:
if (totalCallDurations.containsKey(singleCall[1])) {
duration += totalCallDurations.get(singleCall[1]);
}
totalCallDurations.put(singleCall[1], duration);

Create a map and update the value if the key is present
public static void main(String[] args) {
myMap = new HashMap<>();
// 123,totti 100,roma, 100,totti
addToMap("totti", 123);
addToMap("roma", 100);
addToMap("totti", 100);
System.out.println(myMap);
}
private static void addToMap(String string, int i) {
int t = i;
if (myMap.get(string) != null) {
t += myMap.get(string);
}
myMap.put(string, t);
}

If you're using Java 8, you can do this easily with the Map.merge() method:
totalCallDurations.merge(singleCall[1], duration, Integer::sum);

If you want to make a map that will add the values together instead of replacing, I would recommend extending the Map type to make your own map. Since Map is very abstract. I would extend HashMap. (I suggest this both for code style and because it will make your code more extendable).
public class AdderMap extends HashMap<String, Integer> { // This extends the HashMap class
public Integer get(String key) { // This overrides the Map::get method
if(super.containsKey(key)) return super.get(key); // If the key-value pairing exists, return the value
else return 0; // If it doesn't exist, return 0
}
public Integer put(String key, Integer value) { // This overrides the Map::put method
Integer old_value = this.get(key); // Get the former value of the key-value pairing (which is 0 if it doesn't exist)
super.put(key, old_value + value); // Add the new value to the former value and replace the key-value pairing (this behaves normally when the former value didn't exist)
return old_value; // As per the documentation, Map::put will return the old value of the key-value pairing
}
}
Now, when you initialize your map, make it an AdderMap. Then, you can just use put(String, Integer) and it will add it together.
The advantage of this solution is that it helps with keeping your code clean and it allows you to use this type of map again in the future without needing separate code in your main code. The disadvantage is that it requires another class, and having too many classes can become cluttered.

Related

Inverting a HashMap

I have a HashMap that converts two Strings to words and then it adds the words to the map. I have it so that one key can point to multiple values. Now I'd like to make a loop that inverts the table so that all values point to keys. Don't bother with a key pointing to multiple values in the inverse.
Map<Word,Set<Word>> map = new HashMap<Word,Set<Word>>();
public void add(Word t, Word m) {
if(map.containsKey(t)) {
Set<Word> newM = map.get(t);
newM.add(m);
} else {
Set<Word> newSet = new HashSet<>();
newSet.add(m);
map.put(t, newSet);
}
}
public void add(String t, String m) {
add(new Word(t), new Word(m));
}
public Dictionary inverse() {
}
The main problem you're facing is the very common misuse of a map. In your case you don't realy have a map. You have something vaguely similar, so you deciced to use a map. What you really have is a Set of DictionaryEntry objects with DidctionaryEntry looking something like this:
public class DisctionaryEntry {
private String word;
private Set<String> translations;
}
using that datastructure and adding a addTranslation(String translation) method to it, I think, your question becomes fairly obvious.

Choosing the perfect data structure for the below data in java

I have to choose one data structure for my need below i am explaining the conditions there are following values
abc,def,rty,ytr,dft which all are map to row R1B1 (actully key is combination of R1+B1)
abEERc,dFFFef,rGGty which all are map to row R1B2 (actully key is combination of R1+B2)
KEY VALUE
abc,def,rty,ytr,dft ---> R1B1
abEERc,dFFFef,rGGty ---> R1B2
now, for example, let's say, if i get ytr then i would be able to retrieve R1B1
or, let's say, i get the value rGGty then i would be able to retrieve R1B2
now the case is that matters is of search, complexity and the time taken as the things have to go in sequence
for example, it will first pick the first line to search ytr, it will first match it with abc which will not match then will have to match with def it will not again match then it will match with rty which will not also match then it will finally match with ytr and finally it will find the key R1B1 finally
similarly if the second string need to be searched lets say rGGty then it would scan first row in which it will not find the value then search would continue to second row and also in second row in the third element it would get rGGty as element then it would retrieve R1B2 as value
let's say, if put this thing in map then a sequence search will go on key and then only we will be able to find the corresponding value
Folks please advise which will be the best data structure i can implement in java in which i will have to search the keys items to find the corresponding value in very fast time also which will not hit the performance too
,the kind of data structure performance should be very high
Please advise folks
Key-value pairs can be accessed in O(1) using a HashMap. However if you use HashMap<String, String> then updating the value will be painful because Strings are immutable. This means you will have to check all entry sets and if the value matches update it. So you could create a helper class for the value and let all keys point to an instance of this class. Here is a stub with the most important functions, I guess you can add the rest yourself.
public class MyDataStructure {
private Map<String, MyValue> key_value = new HashMap<String, MyValue>();
private Map<String, MyValue> value_MyValue = new HashMap<String, MyValue>();
public void set(String key, String value) {
MyValue v = value_MyValue.get(value);
if (v == null) { // should rarely happen, could check with containsKey
v = new MyValue(value);
value_MyValue.put(v);
}
key_value.put(key, v);
}
public String get(String key) {
return key_value.get(key).getValue(); // key might not exist
}
public String changeValue(String oldValue, String newValue) {
MyValue v = value_MyValue.remove(oldValue); // oldValue might not exist
v.setValue(newValue);
value_MyValue.put(newValue, v);
// will not work if newValue already exists... then you will have to merge
}
private class MyValue() {
private String value;
public MyValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
I think its best to keep it simple until poor performance shows a need for some kind of improvement. Even if many map values are the same string, that should be ok since Java stores only one copy in heap. If the sets of keys mapped to a single string gets very large some performance improvement may be possible by doing two lookups -- first to determine set membership and second to retrieve the value of the key associated with the set. That would be easy to implement. For now here is an immediately straightforward approach:
import java.util.*;
public class HashMapDemo {
static HashMap<String, String> map = new HashMap<String, String>();
public static void lookup(String key, String value) {
if (map.get(key) == value) {
System.out.println(key + " lookup ok");
} else {
System.out.println(key + " lookup produced" + map.get(key));
}
}
public static void main(String[] args) {
// requirements:
// abc,def,rty,ytr,dft ---> R1B1
// abEERc,dFFFef,rGGty ---> abEERc
Set<String> kset1 = new HashSet<String>(Arrays.asList("abc", "def",
"rty", "ytr", "dft"));
Set<String> kset2 = new HashSet<String>(Arrays.asList("abEERc",
"dFFFef", "rGGty"));
for (String s : kset1) {
map.put(s, "R1B1");
}
for (String s : kset2) {
map.put(s, "abEERc");
}
// testing value lookup with key
for (String s : kset1) {
lookup(s, "R1B1");
}
// prints:
// abc lookup ok
// dft lookup ok
// def lookup ok
// rty lookup ok
// ytr lookup ok
for (String s : kset2) {
lookup(s, "abEERc");
}
// prints:
// rGGty lookup ok
// abEERc lookup ok
// dFFFef lookup ok
// change key "R1B1" to "XYZ"
for (String s : kset1) {
map.put(s, "XYZ");
}
// test the change
for (String s : kset1) {
lookup(s, "XYZ");
}
// prints:
// abc lookup ok
// dft lookup ok
// def lookup ok
// rty lookup ok
// ytr lookup ok
}
}

In java, how can I work with objects which can be either String or List<String>? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Maps with multiple types of values in java
I have an odd question. Maybe I'm going about this the wrong way, but let's see where this question goes :)
I would like a Map container that contains either Strings or lists of Strings. I want to enforce this rule during construction of this object so that you can't create a map with values that aren't either of those.
e.g.
class Record {
public Record(String key, Map<String,Object> attrs) {
// check that attrs only contains Objects which are Strings or List<Strings>
}
}
Other ways I have thought of to solve the problem might be...
1)
class Record {
public Record(String key, Map<String,String> attrs, Map<String,List<String>> multiAttrs) {
// ...
}
}
2)
class Record {
public Record(String key, Map<String,Value> attrs) {
// ...
}
}
class Value {
// Create some funky class that encapsulates lists.
// Perhaps returning the only element in the list if the size is 1,
// but returning the list otherwise
}
I am not immediately excited at the alternatives, but I'm just putting it there as stuff I've already considered. Really I want the distinction between Strings and List to be transparent to the user of the class.
Have you considered ListMultimap? For the single value case the list would only have one element. Multimap allows multiple elements (values) to be mapped to each key. So your method would be:
public Record(String key, ListMultimap<String, String> attrs)...
Also, since your Record seems to be another mapping, consider using Table which allows for two-key mapping.
Check out ArrayListMultimap from Google which will help with this need
You can continue calling put on this map, if you need to get the map in its simplified form you can use this method, or modify it :)
public static Map<Field, String> toSingularMap(ArrayListMultimap<Field, String> map) {
Map<Field, String> singular_map = new HashMap<Field, String>();
if (map != null && !map.isEmpty()) {
Map<Field, Collection<String>> real_map = map.asMap();
for (Iterator<Entry<Field, Collection<String>>> it = real_map
.entrySet().iterator(); it.hasNext();) {
Entry<Field, Collection<String>> entry = it.next();
Field field = entry.getKey();
Collection<String> values = entry.getValue();
String value = null;
if (values != null && !values.isEmpty()) {
ArrayList<String> list = new ArrayList<String>(values);
value = list.get(0);
}
singular_map.put(field, value);
}
}
return singular_map;
}
Or if you do not want to use an extra library, you can create a simple Wrapper class
class Wrap {
String value;
String[] values
}
and have your map use Map<String, Wrap> map, when looping you can then determine either through use of your class methods or just testing, which one of the Wrapper variables are populated
I would use only List<String>. You could maybe add some methods to allow adding a single String and wrap the passed argument using Arrays.asList(...). Using only a single type of objects will reduce the quantity of code to write and avoid many if/else.
Why not create a class
class MyFunkyValue{
private String onlyOneString;
private List<String> stringValues;
public MyFunkyValue(String s){
...
}
public MyFunkyValue(List<String>ls){
...
}
}
and use it like this:
Map<KeyClass,MyFunkyValue> m;

Get key from a HashMap using the value [duplicate]

This question already has answers here:
Java Hashmap: How to get key from value?
(39 answers)
Closed 5 years ago.
I want to get the key of a HashMap using the value.
hashmap = new HashMap<String, Object>();
haspmap.put("one", 100);
haspmap.put("two", 200);
Which means i want a function that will take the value 100 and will return the string one.
It seems that there are a lot of questions here asking the same thing but they don't work for me.
Maybe because i am new with java.
How to do it?
The put method in HashMap is defined like this:
Object put(Object key, Object value)
key is the first parameter, so in your put, "one" is the key. You can't easily look up by value in a HashMap, if you really want to do that, it would be a linear search done by calling entrySet(), like this:
for (Map.Entry<Object, Object> e : hashmap.entrySet()) {
Object key = e.getKey();
Object value = e.getValue();
}
However, that's O(n) and kind of defeats the purpose of using a HashMap unless you only need to do it rarely. If you really want to be able to look up by key or value frequently, core Java doesn't have anything for you, but something like BiMap from the Google Collections is what you want.
We can get KEY from VALUE. Below is a sample code_
public class Main {
public static void main(String[] args) {
Map map = new HashMap();
map.put("key_1","one");
map.put("key_2","two");
map.put("key_3","three");
map.put("key_4","four");
System.out.println(getKeyFromValue(map,"four"));
}
public static Object getKeyFromValue(Map hm, Object value) {
for (Object o : hm.keySet()) {
if (hm.get(o).equals(value)) {
return o;
}
}
return null;
}
}
I hope this will help everyone.
If you need only that, simply use put(100, "one"). Note that the key is the first argument, and the value is the 2nd.
If you need to be able to get by both the key and the value, use BiMap (from guava)
You have it reversed. The 100 should be the first parameter (it's the key) and the "one" should be the second parameter (it's the value).
Read the javadoc for HashMap and that might help you: HashMap
To get the value, use hashmap.get(100).
You mixed the keys and the values.
Hashmap <Integer,String> hashmap = new HashMap<Integer, String>();
hashmap.put(100, "one");
hashmap.put(200, "two");
Afterwards a
hashmap.get(100);
will give you "one"
if you what to obtain "ONE" by giving in 100 then
initialize hash map by
hashmap = new HashMap<Object,String>();
haspmap.put(100,"one");
and retrieve value by
hashMap.get(100)
hope that helps.
public class Class1 {
private String extref="MY";
public String getExtref() {
return extref;
}
public String setExtref(String extref) {
return this.extref = extref;
}
public static void main(String[] args) {
Class1 obj=new Class1();
String value=obj.setExtref("AFF");
int returnedValue=getMethod(value);
System.out.println(returnedValue);
}
/**
* #param value
* #return
*/
private static int getMethod(String value) {
HashMap<Integer, String> hashmap1 = new HashMap<Integer, String>();
hashmap1.put(1,"MY");
hashmap1.put(2,"AFF");
if (hashmap1.containsValue(value))
{
for (Map.Entry<Integer,String> e : hashmap1.entrySet()) {
Integer key = e.getKey();
Object value2 = e.getValue();
if ((value2.toString()).equalsIgnoreCase(value))
{
return key;
}
}
}
return 0;
}
}
If you are not bound to use Hashmap, I would advise to use pair< T,T >.
The individual elements can be accessed by first and second calls.
Have a look at this http://www.cplusplus.com/reference/utility/pair/
I used it here : http://codeforces.com/contest/507/submission/9531943

how to swap key in map?

is there a way to sort this numbers stored in a string variable?
TreeMap<String,List<QBFElement>> qbfElementMap = new TreeMap<String, List<QBFElement>>();
this is the map where the key is :
27525-1813,
27525-3989,
27525-4083,
27525-4670,
27525-4911,
27526-558,
27526-1303,
27526-3641,
27526-4102,
27527-683,
27527-2411,
27527-4342
this is the list of keys and the value for each of the key is a list.
now, how can i sort this key in ascending order by number.
ex. if i want to sort : 1,2,11,20,31,3,10
i want to have as output is : 1,2,3,10,11,20,31
but when i use the autosort of treemap the output goes : 1,10,11,2,20,3,31
how can i sort it in ascending order by numeric?
and the language is java :) thank you:)
The keys in your map are not Integer but String values. That's why the key's are sorted like observed.
Either change the Map to
TreeMap<Long,List<QBFElement>> qbfElementMap
or create it with a specialized Comparatorthat will provide the expected numerical order for the String type keys.
A mapping from your String values to Longs could be done like this:
private Long convertToLongTypeKey(String key) {
String[] parts = key.split("-");
// next lines assumes, that the second part is in range 0...9999
return Long.parseLong(parts[0]) * 10000 + Long.parseLong(parts[1]);
}
An implementation of Comparator<String> could use the same mapping to create a numerical comparision of two String based keys:
new TreeMap<String,List<QBFElement>>(new Comparator<String>(){
#Override
public int compare(String key1, String key2) {
String[] parts1 = key1.split("-");
Long long1 = Long.parseLong(parts1[0]) * 10000 + Long.parseLong(parts1[1]);
String[] parts2 = key2.split("-");
Long long2 = Long.parseLong(parts2[0]) * 10000 + Long.parseLong(parts2[1]);
return long1.compareTo(long2);
}
});
You can change the way that the TreeMap sorts its keys by providing a custom comparator to the constructor. If you want, you can define a new Comparator that compares strings by breaking them up into numeric components.
It seems like a better idea, though, would be to not use Strings as your keys. The data you're using as keys is clearly not textual - it's numeric - and you might want to define a custom type to represent it. For example:
public class KeyType implements Comparable<KeyType> {
private final int first;
private final int second;
public KeyType(int first, int second) {
this.first = first;
this.second = second;
}
#Override
public boolean equals(Object other) {
if (!(other instanceof KeyType)) return false;
KeyType realOther = (KeyType) other;
return realOther.first == first && realOther.second == second;
}
#Override
public int hashCode() {
return first + 31 * second;
}
public int compareTo(KeyType other) {
if (first != other.first)
return first - other.first;
return second - other.second;
}
}
This approach is the most expressive and robust. It gives you better access to the individual fields of the keys you're using, and also prevents you from adding nonsensical keys into the map like the string "Lalalalala". I'd strongly suggest using this approach, or at least one like it. The type system is your friend.
A TreeMap can take a custom comparator for custom sorting. Write a comparator that sorts the keys the way you want and use it when you create the treemap
TreeMap<String,List<QBFElement>> qbfElementMap = new TreeMap<String, List<QBFElement>>(myComparator);

Categories

Resources