Sum value Of Class Objects Property In ArrayList - java

I have an ArrayList which having many objects. I want to do sum of values of the same property name.
Examples Data in Array List which is Objects of ProfitAndLossDataDO
"Michel" , 5000
"Alex" , 5000
"Edvin" , 4000
"Sosha" , 3000
"Michel" , 2000
"Alex" , 3000
And the Result Would be (Sum of values when person are same)-
"Michel" ,7000
"Alex" , 8000
"Edvin" , 4000
"Sosha" , 3000
The Logic class ProfitAndLossDataDO
public class ProfitAndLossDataDO {
String ledgerName;
double ledgerAmount;
public ProfitAndLossDataDO() {
}
public ProfitAndLossDataDO(String ledgerName, double ledgerAmount) {
this.ledgerName = ledgerName;
this.ledgerAmount = ledgerAmount;
}
public String getLedgerName() {
return ledgerName;
}
public void setLedgerName(String ledgerName) {
this.ledgerName = ledgerName;
}
public double getLedgerAmount() {
return ledgerAmount;
}
public void setLedgerAmount(double ledgerAmount) {
this.ledgerAmount = ledgerAmount;
}
#Override
public String toString()
{
return ("ledger name : "+this.getLedgerName()+" Amount : "+this.getLedgerAmount());
}
}
Thanks

I'd iterate the list and collect the results in a map:
public static List<ProfitAndLossDataDO> sumPerLedgerName
(List<ProfitAndLossDataDO> list) {
Map<String, ProfitAndLossDataDO> map = new HashMap<>();
for (ProfitAndLossDataDO p : list) {
String name = p.getLedgerName();
ProfitAndLossDataDO sum = map.get(name);
if (sum == null) {
sum = new ProfitAndLossDataDO(name, 0.0);
map.put(name, sum);
}
sum.setLedgerAmount(sum.getLedgerAmount() + p.getLedgerAmount());
}
return new ArrayList<>(map.values());
}
EDIT:
Java 8's enhancements to the Map interface allow us to implement this method in a slightly more elegant way, with the annoying if block in the middle:
public static List<ProfitAndLossDataDO> sumPerLedgerName
(List<ProfitAndLossDataDO> list) {
Map<String, ProfitAndLossDataDO> map = new HashMap<>();
for (ProfitAndLossDataDO p : list) {
String name = p.getLedgerName();
ProfitAndLossDataDO sum = map.computeIfAbsent(name, n -> new ProfitAndLossDataDO(n, 0.0));
sum.setLedgerAmount(sum.getLedgerAmount() + p.getLedgerAmount());
}
return new ArrayList<>(map.values());
}

You can use a Hash Map as aleroot suggested. Use name as the key and sum as the value. Whenever you need to insert value just check such entry exists with the same key and update it.
public class ProfitAndLossDataDO {
HashMap<String, Double> data = new HashMap<String, Double>();
public ProfitAndLossDataDO() {
}
public void updateLedger(String ledgerName, double ledgerAmount) {
double temp;
if(data.containsKey(ledgerName)) {
temp = data.get(ledgerName)+ledgerAmount;
data.put(ledgerName,temp);
}
else {
data.put(ledgerName,ledgerAmount);
}
}
}

Why you don't just put them in an Map based collection with key/value pairs ?
I think that in this case a Map based collection is more suitable, for the data you have and the context in which you want to use it.
If you need to preserve the single items inside the list, you could use a linked list as Value of the map .
For example :
HashMap<String, LinkedList<Double>> cache = new HashMap<String, LinkedList<Double>>();
and SUM each element of the value LinkedList to find the total amount ... You could even wrap the LinkedList of doubles into a container object with helper functions like getTotal() or Sum().

Related

Return String continuously - Data getting overwritten by ArrayList

Currently creating a tableview using JavaFX and came accross this problem where it would simply append the last element of the array (As all the other elements get overrwritten ..)
public void companyTable() {
for(CompanyData s: companydataList()){
companyDataTableView.getItems().setAll(s);
}
}
Where companyDataList is:
private List<CompanyData> companydataList(){
CompanyData company = new CompanyData("test",9,1);
for(String i : sim.getCompanyNames()) {
company.setPFCompanyName(i);
}
for(int j : sim.getCompanyValues()) {
company.setPFShareValues(j);
}
List<CompanyData> companydata = new ArrayList<>();
companydata.add(company);
return companydata;
}
The data gets added to this (Setters and getters of Strings)
private final StringProperty PFCompanyName;
private final IntegerProperty PFShareValues;
public CompanyData(String CompanyName, int ShareValue, int ClosingPence) {
this.PFCompanyName = new SimpleStringProperty(CompanyName);
this.PFShareValues = new SimpleIntegerProperty(ShareValue);
}
public String getPFCompanyName() {
return PFCompanyName.get();
}
public StringProperty PFCompanyNameProperty() {
return PFCompanyName;
}
public void setPFCompanyName(String PFCompanyName) {
this.PFCompanyName.set(PFCompanyName);
}
public int getPFShareValues(int j) {
return PFShareValues.get();
}
public IntegerProperty PFShareValuesProperty() {
return PFShareValues;
}
public void setPFShareValues(int PFShareValues) {
this.PFShareValues.set(PFShareValues);
}
Currently the output is:
CompanyName CompanyValue
Samsung 1093
But what I desire is:
CompanyName CompanyValue
Nokia 3
Apple 1
HTC 9
Samsung 1093
The method setAll(...) replaces all the elements currently in the list with the ones you provide (it "sets them all"). So each time you iterate through your loop, you replace all the elements with the current one. At the end you will just have one element in the table.
An ObservableList is a subtype of the standard java.util.List, so you can call any of the standard list methods. E.g. you can just add each element instead:
public void companyTable() {
for(CompanyData s: companydataList()){
companyDataTableView.getItems().add(s);
}
}
Of course, you don't really need to write the loop yourself, you can just add them all:
public void companyTable() {
companyDataTableView.getItems().addAll(companydataList());
}
or, if it's what you need, set them all:
public void companyTable() {
companyDataTableView.getItems().setAll(companydataList());
}
Furthermore, your companydataList() method only creates one CompanyData instance, and then constantly changes it. Here is your current implementation, with comments explaining what each line you wrote does:
private List<CompanyData> companydataList(){
// create a single instance:
CompanyData company = new CompanyData("test",9,1);
// repeatedly change the name of that instance:
for(String i : sim.getCompanyNames()) {
company.setPFCompanyName(i);
}
// repeatedly change the value of that instance:
for(int j : sim.getCompanyValues()) {
company.setPFShareValues(j);
}
// create an empty list:
List<CompanyData> companydata = new ArrayList<>();
// add one object to the list
companydata.add(company);
// return the list containing the single object:
return companydata;
}
You need to create a CompanyData instance for each of the name/value pairs, and add each instance to the list. Assuming sim.getCompanyNames() and sim.getCompanyValues() return lists (or arrays; I will assume they are lists) of the same length, you need to do something like
private List<CompanyData> companydataList(){
List<String> companyNames = sim.getCompanyNames();
List<Integer> companyValues = sim.getCompanyValues();
List<CompanyData> companydata = new ArrayList<>();
for (int i = 0 ; i < companyNames.size(); i++) {
String name = companyNames.get(i);
int value = companyValues.get(i);
CompanyData company = new CompanyData();
company.setPFCompanyName(name);
company.setPFShareValues(value);
companydata.add(company);
}
return companydata;
}
Obviously, it would be far more sensible to have sim, which I assume is some kind of data accessor, return a List<CompanyData> directly in the first place, instead of two different lists for the different properties.

Read objects content from hashmaps

I need to save pairs (string,object) into a hashmap. Basically I managed to populate the hashmap but I don't know how to access the values stored into memory.
This is my code:
HashMap<String, speedDial> SDs = new HashMap<String, speedDial>();
speedDial sd = new speedDial();
SDs.put(String.valueOf(temp),sd); whre temp is my index and sd my object
Then I fill in data into the sd reading them from an xml file.
When I debug the project with eclypse I can see the values are stored correctly into memory, but I've no idea how to retrive the string values associated to the object, see below the SD object format
class speedDial{
String label, dirN;
speedDial (String l, String dN) {
this.label = l;
this.dirN = dN;
}
}
See the picture below: it highlights the data I'm trying to access!
enter image description here
When I try to access the hashmap and print it's values I only got the last one, I use the following:
for ( int k = 0; k <50; k++) {
speedDial.printSD(SDs.get(String.valueOf(k)));
}
This is my printSD method taken from the speedDial class:
public static void printSD (speedDial SD) {
System.out.println("Dir.N: " + SD.dirN + " Label: " + SD.label);
}
And this is the output for all the 50 iterations, that is the last element I added to the hashmap in another for cycle that reads from a xml file.
Dir.N: 123450 Label: label5
Given a HashMap such as:
SpeedDial speedDial1 = new SpeedDial("test1", "test2");
SpeedDial speedDial2 = new SpeedDial("test3", "test4");
SpeedDial speedDial3 = new SpeedDial("test5", "test6");
HashMap<String, SpeedDial> exampleHashMap = new HashMap<>(3);
exampleHashMap.put("key1", speedDial1);
exampleHashMap.put("key2", speedDial2);
exampleHashMap.put("key3", speedDial3);
You can retrieve the value for a given key like so:
SpeedDial exampleOfGetValue = exampleHashMap.get("key1");
System.out.println(exampleOfGetValue.label);
System.out.println(exampleOfGetValue.dirN);
This outputs:
test1
test2
If you want to retrieve the keys for a given value then you could use something like:
public final <S, T> List<S> getKeysForValue(final HashMap<S, T> hashMap, final T value) {
return hashMap.entrySet()
.stream()
.filter(entry -> entry.getValue().equals(value))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
If you call this function like so:
List<String> exampleOfGetKeys = getKeysForValue(exampleHashMap, speedDial1);
System.out.println(exampleOfGetKeys);
It would output a list of all keys that have this value:
[key1]
The following code will iterate through the map and will store the key and values in two lists.
List<String> keys = new ArrayList();
List<Object> values = new ArrayList();
for (Map.Entry<String, Object> speedDial: SDs.entrySet()) {
Object speedDialValue = speedDial.getValue();
String key= speedDial.getKey();
keys.add(key);
values.add(speedDialValue);
}
To retrieve the String value, typically getters are used as it is recommended to use the private modifier for your class attributes.
public class speedDial{
private String label, dirN;
public speedDial (String l, String dN) {
this.label = l;
this.dirN = dN;
}
public String getLabel(){
return this.label;
}
public String getDirN(){
return this.dirN;
}
}
The you can simply use yourObject.getLabel(); or yourObject.getDirN();
Hope that helps!
SDs.keySet() Gives you the Set of the keys of your HashMap
You can have the list of values using
for (String mapKey : SDs.keySet()) {
System.out.println("key: "+mapKey+" value: "+ SDs.get(mapKey).toString());
}
Yous have to write a toString() fonction for your speedDial

Add Key and Value into an Priority Queue and Sort by Key in Java

I am trying to take in a List of strings and add them into a Priority Queue with Key and Value. The Key being the word and the value being the string value of the word. Then I need to sort the queue with the highest string value first. The priority queue is not letting me add 2 values.
public static List<String> pQSortStrings(List<String> strings) {
PriorityQueue<String, Integer> q = new PriorityQueue<>();
for (int x = 0; x < strings.size(); x++) {
q.add(strings.get(x),calculateStringValue(strings.get(x)));
}
return strings;
}
Problem
PriorityQueue can store a single object in it's each node. So what you are trying to do can not be done as it is.
But you can compose both objects in a single class and then use the PriorityQueue.
You would either need to supply a Comparator or rely on natural ordering by implementing Comparable interface.
Solution
Create a class which has String and int as it's members.
public class Entry {
private String key;
private int value;
// Constructors, getters etc.
}
Implement Comparable interface and delegate comparison to String.
public class Entry implements Comparable<Entry> {
private String key;
private int value;
public Entry(String key, int value) {
this.key = key;
this.value = value;
}
// getters
#Override
public int compareTo(Entry other) {
return this.getKey().compareTo(other.getKey());
}
}
Build the PriorityQueue using this class.
PriorityQueue<Entry> q = new PriorityQueue<>();
Add elements as following.
q.add(new Entry(strings.get(x), calculateStringValue(strings.get(x))));
Hope this helps.
Using Java-8
PriorityQueue<Map.Entry<String, Integer>> queue = new PriorityQueue<>(Map.Entry.comparingByValue(Comparator.reverseOrder()));
to add a new Entry
queue.offer(new AbstractMap.SimpleEntry<>("A", 10));
Solution
public static List<String> pQSortStrings(List<String> strings) {
Queue<String> pq = new PriorityQueue<>((a, b) ->
calculateStringValue(b) - calculateStringValue(a));
for (String str : strings) {
pq.add(str);
}
return strings;
}
Explanation
I believe that the cleanest way to do this is to store Strings in your pq and use a small custom Comparator.
In this case, we want to use calculateStringValue and the pq should return highest String values first. Therefore, make a pq of entries and use the following Comparator:
1 Queue<String> pq = new PriorityQueue<>(new Comparator<String>() {
2 #Override
3 public int compare(String a, String b) {
4 return calculateStringValue(b) - calculateStringValue(a);
5 }
6 });
7 for (String str : strings) {
8 pq.add(str);
9 }
10 return strings;
Simpler syntax for the Comparator, replacing lines 1 - 6, is:
Queue<String> pq = new PriorityQueue<>((a, b) ->
calculateStringValue(b) - calculateStringValue(a));
If you wanted to return smallest String values first, you could just switch the order around for a and b in the Comparator:
...new PriorityQueue<>((a, b) -> calculateStringValue(a) - calculateStringValue(b));
In general, the pattern a - b sorts by smallest first, and b - a sorts by largest values first.
Many good answers are already present but I am posting this answer because no one has used hashmap in their answers.
You can also make the priority Queue from HashMaps bellow is the example for the same. I am creating a max priority queue.
Mind well here I am considering that your hashmap contains only one Entry
PriorityQueue<HashMap<Character, Integer>> pq = new PriorityQueue<>((a, b) -> {
char keyInA = a.keySet().iterator().next(); // key of a
char keyInB = b.keySet().iterator().next(); // key of b
return b.get(keyInB) - a.get(keyInA);
});
For Insertion of the value in the priority queue.
pq.add(new HashMap<>() {
{
put('a', 0);
}
});
Define a class with a key field and a value field
Class MyClass{
int key;
String value
}
Queue<MyClass> queue = new PriorityQueue<>(Comparotor.comparingInt(a -> a.key));
Adding to #Tanmay Patil Answer, If you are using Java 8, You can use lambda for more concise code as comparator interface is a functional interface.
public class CustomEntry {
private String key;
private int value;
public CustomEntry(String key, int value) {
this.key = key;
this.value = value;
}
// getters etc.
}
Now below is the updated code
public static List<String> pQSortStrings(List<String> strings) {
PriorityQueue<CustomEntry> q = new PriorityQueue<>((x, y) -> {
// since you want to sort by highest value first
return Integer.compare(y.getValue(), x.getValue());
});
for (int x = 0; x < strings.size(); x++) {
q.add(new CustomEntry(strings.get(x),calculateStringValue(strings.get(x))));
}
return strings;
}
To use this priority queue
CustomEntry topEntry = q.peek();
System.out.println("key : " + topEntry.getKey());
System.out.println("value : " + topEntry.getValue());
Same logic can be also be applied by using Map.Entry<String, Integer> provided by java for storing key, pair value

Duplicate elements in ArrayList

I have two array list, One is to save name and other is to save quantity. I want to avoid duplicate in the array list. Name array list contains name and its corresponding quantity is contained in quantity array list.
My array list can contains duplicate names, I want to traverse array list to check the name if already exists, if it exists then add the quantity to the previous value and delete duplicate entry.
Eg
Name Quantity
ABC 20
xyz 10
ABC 15
Output Required
Name Quantity
ABC 35
XYZ 10
Thanks
You should use a Map instead, which will not allow for duplicate entries. You use it something like this:
Map<String, Integer> nameToQuantityMap = new HashMap<String, Integer>():
nameToQuantityMap.put("Mr Smith", 100);
nameToQuantityMap.put("Mrs Jones", 500);
EDIT: Now that you've edited the question, the answer is different. If you want to add the values of duplicate keys, you'll have to do something like this:
// For each (name, quantity) pair
if (nameToQuantityMap.containsKey(name) ) {
Integer sum = nameToQuantityMap.get(name) + quantity;
nameToQuantityMap.put(name, sum);
}
else {
nameToQuantityMap.put(name, quantity);
}
I want to avoid duplicate in the array list.
In that case use HashSet
Or else if you have 2 parallel ArrayList then you can use HashMap
The structure you attempt to represent resembles something that should be represented by a Map, which is a key -> value storage type of structure. Having two lists and trying to keep the in sync is a bad idea.
Use java.util.Map where key would be you map and value would be value.
Map<String,Integer> map = new HashMap<>();
if(map.get(name)!=null){
Integer oValue = map.get(name)+nNalue;
}else
map.put(name,value);
Try this if you want to add value to the previous value if Key already exists .
public class Example {
static Map<String, Integer> map = new HashMap<String, Integer>();
public static void main(String[] args) {
insertNameAndQuantity("A", 10);
insertNameAndQuantity("B", 25);
insertNameAndQuantity("A", 25);
System.out.println(map);
}
public static void insertNameAndQuantity(String key, Integer value) {
Integer count = map.get(key);
if (count == null)
map.put(key, value);
else
map.put(key, count + value);
}
}
Output:
{A=35, B=25}
this is an example implement on c# code.
public class temp
{
[Test]
public void T()
{
var list1 = new ArrayList(){"ABC", "xyz", "ABC"};
var list2 = new ArrayList() {20, 10, 15};
var nameList = new List<string>();
var list1result = new ArrayList();
var list2result = new ArrayList();
int index = 0;
foreach (string name in list1)
{
if (!nameList.Contains(name))
{
list1result.Add(name);
var quantity = list2[index] ?? 0;
list2result.Add(quantity);
nameList.Add(name);
}
else
{
var index2 = 0;
foreach (string name2 in list1result)
{
if (name2 == name)
{
list2result[index2] = (int)list2result[index2] + (int)list2[index];
}
index2++;
}
}
index++;
}
Assert.True(list1result.Count == 2, list1result.Count + " t1");
}
}
I've tested the output, it's correct.

Is there a Java Class similar to ArrayList that can do this?

I have been running into this problem sometimes when programming.
Imagine I have a table of data with two columns. The first column has strings, the second column has integers.
I want to be able to store each row of the table into a dynamic array. So each element of the array needs to hold a string and an integer.
Previously, I have been accomplishing this by just splitting each column of the table into two separate ArrayLists and then when I want to add a row, I would call the add() method once on each ArrayList. To remove, I would call the remove(index) method once on each ArrayList at the same index.
But isn't there a better way? I know there are classes like HashMap but they don't allow duplicate keys. I am looking for something that allows duplicate entries.
I know that it's possible to do something like this:
ArrayList<Object[]> myArray = new ArrayList<Object[]>();
myArray.add(new Object[]{"string", 123});
I don't really want to have to cast into String and Integer every time I get an element out of the array but maybe this is the only way without creating my own? This looks more confusing to me and I'd prefer using two ArrayLists.
So is there any Java object like ArrayList where it would work like this:
ArrayList<String, Integer> myArray = new ArrayList<String, Integer>();
myArray.add("string", 123);
Just create simple POJO class to hold row data. Don't forget about equals and hashCode and prefer immutable solution (without setters):
public class Pair {
private String key;
private Integer value;
public Pair(String key, Integer value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public Integer getValue() {
return value;
}
// autogenerated
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Pair)) return false;
Pair pair = (Pair) o;
if (key != null ? !key.equals(pair.key) : pair.key != null) return false;
if (value != null ? !value.equals(pair.value) : pair.value != null) return false;
return true;
}
#Override
public int hashCode() {
int result = key != null ? key.hashCode() : 0;
result = 31 * result + (value != null ? value.hashCode() : 0);
return result;
}
}
Usage:
List<Pair> list = new ArrayList<Pair>();
list.add(new Pair("string", 123));
Note: in other languages there are build-in solutions for it like case-classes and tuples in Scala.
Create a Row class that holds the data.
package com.stackoverflow;
import java.util.ArrayList;
import java.util.List;
/**
* #author maba, 2012-10-10
*/
public class Row {
private int intValue;
private String stringValue;
public Row(String stringValue, int intValue) {
this.intValue = intValue;
this.stringValue = stringValue;
}
public int getIntValue() {
return intValue;
}
public String getStringValue() {
return stringValue;
}
public static void main(String[] args) {
List<Row> rows = new ArrayList<Row>();
rows.add(new Row("string", 123));
}
}
You can create very simple object, like :
public class Row{
private String strVal;
private Integer intVal;
public Row(String s, Integer i){
strVal = s;
intVal = i;
}
//getters and setters
}
Then use it as follows :
ArrayList<Row> myArray = new ArrayList<Row>();
myArray.add(new Row("string", 123));
Map is the option if you are sure that any one value among integer or string is unique. Then you can put that unique value as a key. If it is not true for your case, creating a simple POJO is best option for you. Infact, if in future, there a chance to come more values (columns) per row then also using a POJO will be less time consuming. You can define POJO like;
public class Data {
private int intValue;
private String strValue;
public int getIntValue() {
return intValue;
}
public void setIntValue(int newInt) {
this.intValue = newInt;
}
public String getStrValue() {
return strValue;
}
public void setStrValue(String newStr) {
this.strValue = newStr;
}
And in the class you can use it like;
ArrayList<Data> dataList = new ArrayList<Data>();
Data data = new Data();
data.setIntValue(123);
data.setStrValue("string");
dataList.add(data);
You should create a class (e.g. Foo) that contains an int and a String.
Then you can create an ArrayList of Foo objects.
List<Foo> fooList = new ArrayList<Foo>();
This is called a map my friend. It is similar to a dictionary in .net
http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
HashMap my be the class you are looking for assuming "string" going to different for different values. Here is documentation on HashMap
Example:
HashMap<String, Integer> tempMap = new HashMap<String, Integer>();
tempMap.put("string", 124);
If you need to add more than one value, you may create HashMap<String, ArrayList> like that.
you can use google collection library Guava there is a Map called Multimap. It is collection similar to a Map, but which may associate multiple values with a single key. If you call put(K, V) twice, with the same key but different values, the multimap contains mappings from the key to both values.
Use Map to solve this problem:
Map<String, Integer> map = new HashMap<String, Integer>();
Eg:
map.put("string", 123);

Categories