Arraylist - String/Double - java

I am taking a basic objects first with java class, i don't know much yet and need a little help ..
I need to assign these values to an arraylist but also need to allow the user to choose a health option based on a string that will then output the value related to the option..
double [] healthBenDesig = new double [5];
double [] healthBenDesig = {0.00, 311.87, 592.56, 717.30, 882.60};
Strings I want to assign are:
none = 0.00
employeeOnly = 311.87
spouse = 592.56
children = 717.30
kids = 882.60
Ultimately, I want the user to input for example "none" and the output will relate none to the value held in the arraylist [0] slot and return that value. Is this possible? Or is there an easier way I am overlooking?
if anyone could help me out I would really appreciate it :)
Thanks

Yes. This is possible with HashMap.
HashMap<String,Double> healthMap = new HashMap<String,Double>();
healthMap.put("none",0.00);
healthMap.put("employeeOnly",311.87);
healthMap.put("spouse",592.56);
healthMap.put("children",717.30);
healthMap.put("kids",882.60);
Now, when user enters none then use get() method on healthMap to get the value.
For safety check that key exists in map using containsKey() method.
if(healthMap.containsKey("none")) {
Double healthVal = healthMap.get("none"); //it will return Double value
} else {
//show you have entered wrong input
}
See also
HashMap oracle docs

Best solution is Map<String, Double>.
Map<String,Double> map=new HashMap<>();
map.put("none",0.0);
Now when you want the value for "none" you can use get() method
map.get("none") // will return 0.0

Here's something for you to get started with since it's the assignment:
Create a Map<String, Double> that holds the number and string as key/value pair.
Store the above values into the map
When a user enters the input, capture it using Scanner
Do something like this.
if(map.containsKey(input)) {
value = map.get(input);
}

Use Map Inteface
Map<String, Double> healthBenDesig =new HashMap<String, Double>();
healthBenDesig.put("none", 0.00);
healthBenDesig.put("employeeOnly", 311.87);
healthBenDesig.put("spouse", 592.56);
healthBenDesig.put("children", 717.30);
healthBenDesig.put("kids", 882.60);
System.out.println(healthBenDesig);
OutPut
{
none = 0.0,
spouse = 592.56,
children = 717.3,
kids = 882.6,
employeeOnly = 311.87
}

Related

How to SUM duplicate key values in LinkedHashMap?

I have a LinkedHashMap where I have two duplicate keys with their correspondent values, I need to know how to SUM those values into one key. Currently he eliminates the old duplicated value and put the new one
This is my Map
static Map<String, Double> costByDuration = new LinkedHashMap<>();
This is where I put the values ( call_from can be 912345678 and have a value of 10, and then another call from 912345678 and have a value of 20), then I want 912345678 to have a value of 30 instead of keeping only one.
costByDuration.put(call_from, toPay);
I'd create a method as follows:
public void put(String key, Double value){
costByDuration.merge(key,value , Double::sum);
}
then the use case would be:
put(call_from, toPay);
put(anotherKey, anotherValue);
...
...
This solution internally uses the merge method which basically says if the specified key is not already associated with a value or is associated with null, associates it with the given non-null value. Otherwise, replaces the associated value with the results of the given remapping function.
You'll have to check first whether your value is already in the map.
Double existingValue = costByDuration.get(callFrom);
if (existingValue != null) {
costByDuration.put(callFrom, existingValue + toPay);
} else {
costByDuration.put(callFrom, toPay);
}
Incidentally, it's a bad idea to use a Double to store an amount of money, if you want your arithmetic operations to give you the correct answer. I strongly recommend using BigDecimal in place of Double.
Use merge function:
costByDuration.merge(call_from, toPay, (oldPay, toPay) -> oldPay + toPay);
Try this using containsKey method :
static Map<String, Double> costByDuration = new LinkedHashMap<>();
if(costByDuration.containsKey(call_from) {
costByDuration.put(call_from, map.get(call_from) + to_Pay);
} else {
costByDuration.put(call_from, to_Pay);
}

Changing LinkedHashMapValues

Below is data from 2 linkedHashMaps:
valueMap: { y=9.0, c=2.0, m=3.0, x=2.0}
formulaMap: { y=null, ==null, m=null, *=null, x=null, +=null, c=null, -=null, (=null, )=null, /=null}
What I want to do is input the the values from the first map into the corresponding positions in the second map. Both maps take String,Double as parameters.
Here is my attempt so far:
for(Map.Entry<String,Double> entryNumber: valueMap.entrySet()){
double doubleOfValueMap = entryNumber.getValue();
for(String StringFromValueMap: strArray){
for(Map.Entry<String,Double> entryFormula: formulaMap.entrySet()){
String StringFromFormulaMap = entryFormula.toString();
if(StringFromFormulaMap.contains(StringFromValueMap)){
entryFormula.setValue(doubleOfValueMap);
}
}
}
}
The problem with doing this is that it will set all of the values i.e. y,m,x,c to the value of the last double. Iterating through the values won't work either as the values are normally in a different order those in the formulaMap. Ideally what I need is to say is if the string in formulaMap is the same as the string in valueMap, set the value in formulaMap to the same value as in valueMap.
Let me know if you have any ideas as to what I can do?
This is quite simple:
formulaMap.putAll(valueMap);
If your value map contains key which are not contained in formulaMap, and you don't want to alter the original, do:
final Map<String, Double> map = new LinkedHashMap<String, Double>(valueMap);
map.keySet().retainAll(formulaMap.keySet());
formulaMap.putAll(map);
Edit due to comment It appears the problem was not at all what I thought, so here goes:
// The result map
for (final String key: formulaMap.keySet()) {
map.put(formulaMap.get(key), valueMap.get(key));
// Either return the new map, or do:
valueMap.clear();
valueMap.putAll(map);
for(Map.Entry<String,Double> valueFormula: valueMap.entrySet()){
formulaMap.put(valueFormula.getKey(), valueFormula.value());
}

Comparing java variables and printing

Suppose , I have some variables as :
String x="abcd";
String y="qwert";
String z="mnvji";
and more...
I take an input from user.
If user inputs 'x' , I print that string i.e. I print "abcd"
If user inputs 'y' , I print "qwert" and so on...
Is there any way to do it without switches or ifs??
Thank you,friends, in advance.
You could create a map from input string to result. Initialize the map:
Map<String, String> map = new HashMap<String, String>();
map.put("x", "abcd");
map.put("y", "qwert");
map.put("z", "mnvji");
And when you want to print the result from the input from the user:
Scanner s = new Scanner(System.in);
while (s.hasNextLine())
System.out.println(map.get(s.nextLine()));
Local variable names aren't available at runtime and reading field knowing it's name requires some reflection (see #amit's answer). You need a map:
Map<String, String> map = new HashMap<>();
map.put("x", "abcd");
map.put("y", "qwert");
map.put("z", "mnvji");
Now just take value from that map:
String value = map.get(userInput);
value will be null if it doesn't match any of x/y/z.
As we can approach like that also,
String input[]=new String['z'];
input['X']="abcd";
input['Y']="qwert";
input['Z']="mnvji";
System.out.println(input['X']);
But it will come under some limitation
Map collection using key value pair implementation solve your problem .
put varible x,y,z as key and "abcd" ,.. as value.
Retrieve value from specific key according to input value.
Map<String, String> map = new HashMap<String, String>();
map.put("x", "abcd");
map.put("y", "qwert");
map.put("z", "mnvji");
to get value
String value = map .get(inputValue).
Map<String, String> map = new HashMap<>();
map.put("x", "abcd");
map.put("y", "qwert");
map.put("z", "mnvji");
Scanner s = new Scanner(System.in);
while (s.hasNextLine())
System.out.println(map.get(s.nextLine()));
will probably work.
Put your variable set into a HashMap as (key,value) pairs and just retrieve the value for the particular key when user inputs the key.
create an string array in which x,y,z should be indexes and store the content relatively ...
get the user input and pass it to the array as index ..you will get it..
If you really don't want to use switches or ifs (and I'd assume you include maps in that) then you'd have to use reflection to get the names of all the variables and decide which to print on them. Here's the basics:
Class yourClass = Class.forName("yourpackagename.YourClassName")
Field[] allFields = yourClass.getDeclaredFields();
String[] fieldNames = new String[allFields.length];
for(int i = 0; i < fieldNames.length; i++)
{
fieldNames[i] = allFields [i].getName();
}
//Get name of field user wants to display, and look it up in
//the fieldNames array to get the index of it, store this index
Object instance = yourClass.newInstance();
System.out.println(allFields[indexToDisplay].get(instance));
Of course, this could well be overkill.
If you have no choice but using object variables (fields) and not a Map as suggested by other answers - you might want to use reflection, and specifically the Class.getField() and Class.getDeclaredField() methods-
Field f = MyClass.class.getDeclaredField("x");
System.out.println(f.get(myObject));
Where MyClass is your class name and myObject is the object you want the value from.
Note that with this approach - you cannot add fields - you can only get existing ones.

How to optimize the updating of values in an ArrayList<Integer>

I want to store all values of a certain variable in a dataset and the frequency for each of these values. To do so, I use an ArrayList<String> to store the values and an ArrayList<Integer> to store the frequencies (since I can't use int). The number of different values is unknown, that's why I use ArrayList and not Array.
Example (simplified) dataset:
a,b,c,d,b,d,a,c,b
The ArrayList<String> with values looks like: {a,b,c,d} and the ArrayList<Integer> with frequencies looks like: {2,3,2,2}.
To fill these ArrayLists I iterate over each record in the dataset, using the following code.
public void addObservation(String obs){
if(values.size() == 0){// first value
values.add(obs);
frequencies.add(new Integer(1));
return;//added
}else{
for(int i = 0; i<values.size();i++){
if(values.get(i).equals(obs)){
frequencies.set(i, new Integer((int)frequencies.get(i)+1));
return;//added
}
}
// only gets here if value of obs is not found
values.add(obs);
frequencies.add(new Integer(1));
}
}
However, since the datasets I will use this for can be very big, I want to optimize my code, and using frequencies.set(i, new Integer((int)frequencies.get(i)+1)); does not seem very efficient.
That brings me to my question; how can I optimize the updating of the Integer values in the ArrayList?
Use a HashMap<String,Integer>
Create the HashMap like so
HashMap<String,Integer> hm = new HashMap<String,Integer>();
Then your addObservation method will look like
public void addObservation(String obs) {
if( hm.contains(obs) )
hm.put( obs, hm.get(obs)+1 );
else
hm.put( obs, 1 );
}
I would use a HashMap or a Hashtable as tskzzy suggested. Depending on your needs I would also create an object that has the name, count as well as other metadata that you might need.
So the code would be something like:
Hashtable<String, FrequencyStatistics> statHash = new Hashtable<String, FrequencyStatistics>();
for (String value : values) {
if (statHash.get(value) == null) {
FrequencyStatistics newStat = new FrequencyStatistics(value);
statHash.set(value, newStat);
} else {
statHash.get(value).incrementCount();
}
}
Now, your FrequencyStatistics objects constructor would automatically set its inital count to 1, while the incrementCound() method would increment the count, and perform any other statistical calculations that you might require. This should also be more extensible in the future than storing a hash of the String with only its corresponding Integer.

how to manipulate list in java

Edit: My list is sorted as it is coming from a DB
I have an ArrayList that has objects of class People. People has two properties: ssn and terminationReason. So my list looks like this
ArrayList:
ssn TerminatinoReason
123456789 Reason1
123456789 Reason2
123456789 Reason3
568956899 Reason2
000000001 Reason3
000000001 Reason2
I want to change this list up so that there are no duplicates and termination reasons are seperated by commas.
so above list would become
New ArrayList:
ssn TerminatinoReason
123456789 Reason1, Reason2, Reason3
568956899 Reason2
000000001 Reason3, Reason2
I have something going where I am looping through the original list and matching ssn's but it does not seem to work.
Can someone help?
Code I was using was:
String ssn = "";
Iterator it = results.iterator();
ArrayList newList = new ArrayList();
People ob;
while (it.hasNext())
{
ob = (People) it.next();
if (ssn.equalsIgnoreCase(""))
{
newList.add(ob);
ssn = ob.getSSN();
}
else if (ssn.equalsIgnoreCase(ob.getSSN()))
{
//should I get last object from new list and append this termination reason?
ob.getTerminationReason()
}
}
To me, this seems like a good case to use a Multimap, which would allow storing multiple values for a single key.
The Google Collections has a Multimap implementation.
This may mean that the Person object's ssn and terminationReason fields may have to be taken out to be a key and value, respectively. (And those fields will be assumed to be String.)
Basically, it can be used as follows:
Multimap<String, String> m = HashMultimap.create();
// In reality, the following would probably be iterating over the
// Person objects returned from the database, and calling the
// getSSN and getTerminationReasons methods.
m.put("0000001", "Reason1");
m.put("0000001", "Reason2");
m.put("0000001", "Reason3");
m.put("0000002", "Reason1");
m.put("0000002", "Reason2");
m.put("0000002", "Reason3");
for (String ssn : m.keySet())
{
// For each SSN, the termination reasons can be retrieved.
Collection<String> termReasonsList = m.get(ssn);
// Do something with the list of reasons.
}
If necessary, a comma-separated list of a Collection can be produced:
StringBuilder sb = new StringBuilder();
for (String reason : termReasonsList)
{
sb.append(reason);
sb.append(", ");
}
sb.delete(sb.length() - 2, sb.length());
String commaSepList = sb.toString();
This could once again be set to the terminationReason field.
An alternative, as Jonik mentioned in the comments, is to use the StringUtils.join method from Apache Commons Lang could be used to create a comma-separated list.
It should also be noted that the Multimap doesn't specify whether an implementation should or should not allow duplicate key/value pairs, so one should look at which type of Multimap to use.
In this example, the HashMultimap is a good choice, as it does not allow duplicate key/value pairs. This would automatically eliminate any duplicate reasons given for one specific person.
What you might need is a Hash. HashMap maybe usable.
Override equals() and hashCode() inside your People Class.
Make hashCode return the people (person) SSN. This way you will have all People objects with the same SSN in the same "bucket".
Keep in mind that the Map interface implementation classes use key/value pairs for holding your objects so you will have something like myHashMap.add("ssn",peopleobject);
List<People> newlst = new ArrayList<People>();
People last = null;
for (People p : listFromDB) {
if (last == null || !last.ssn.equals(p.ssn)) {
last = new People();
last.ssn = p.ssn;
last.terminationReason = "";
newlst.add(last);
}
if (last.terminationReason.length() > 0) {
last.terminationReason += ", ";
}
last.terminationReason += p.terminationReason;
}
And you get the aggregated list in newlst.
Update: If you are using MySQL, you can use the GROUP_CONCAT function to extract data in your required format. I don't know whether other DB engines have similar function or not.
Update 2: Removed the unnecessary sorting.
Two possible problems:
This won't work if your list isn't sorted
You aren't doing anything with ob.getTerminationReason(). I think you mean to add it to the previous object.
EDIT: Now that i see you´ve edited your question.
As your list is sorted, (by ssn I presume)
Integer currentSSN = null;
List<People> peoplelist = getSortedList();//gets sorted list from DB.
/*Uses foreach construct instead of iterators*/
for (People person:peopleList){
if (currentSSN != null && people.getSSN().equals(currentSSN)){
//same person
system.out.print(person.getReason()+" ");//writes termination reason
}
else{//person has changed. New row.
currentSSN = person.getSSN();
system.out.println(" ");//new row.
system.out.print(person.getSSN()+ " ");//writes row header.
}
}
If you don´t want to display the contents of your list, you could use it to create a MAP and then use it as shown below.
If your list is not sorted
Maybe you should try a different approach, using a Map. Here, ssn would be the key of the map, and values could be a list of People
Map<Integer,List<People>> mymap = getMap();//loads a Map from input data.
for(Integer ssn:mymap.keyset()){
dorow(ssn,mymap.get(ssn));
}
public void dorow(Integer ssn, List<People> reasons){
system.out.print(ssn+" ");
for (People people:reasons){
system.out.print(people.getTerminationReason()+" ");
}
system.out.println("-----");//row separator.
Last but not least, you should override your hashCode() and equals() method on People class.
for example
public void int hashcode(){
return 3*this.reason.hascode();
}

Categories

Resources