Use values from previous row to aggregate values when row missing - java

I have a whole bunch of rows that contain tax payments.
Each row contains PaymentDueDate.
If row is missing in between PaymentDueDates, I have to use same values from previous row to aggregate for all totals.
In below example, between Row="2" and Row="3", data is missing for months 2015/09, 2015/10, 2015/11, 2015/12, 2016/01, 2016/02.
So, I have to use Row="2" values to use to account for missing rows.
<PaymentChangeMaintenance>
<PaymentChangeMaintenanceTransaction Row="1">
<BuydownSubsidyAmount>0.00</BuydownSubsidyAmount>
<AnnualInterestRate>4.75000</AnnualInterestRate>
<PIAmount>689.79</PIAmount>
<PaymentDueDate>2015-07-01</PaymentDueDate>
<CityTaxAmount>23.22</CityTaxAmount>
<CountyTaxAmount>32.25</CountyTaxAmount>
</PaymentChangeMaintenanceTransaction>
<PaymentChangeMaintenanceTransaction Row="2">
<BuydownSubsidyAmount>0.00</BuydownSubsidyAmount>
<AnnualInterestRate>4.75000</AnnualInterestRate>
<PIAmount>689.79</PIAmount>
<PaymentDueDate>2015-08-01</PaymentDueDate>
<CityTaxAmount>125.25</CityTaxAmount>
<CountyTaxAmount>666.22</CountyTaxAmount>
</PaymentChangeMaintenanceTransaction>
<PaymentChangeMaintenanceTransaction Row="3">
<BuydownSubsidyAmount>0.00</BuydownSubsidyAmount>
<AnnualInterestRate>4.75000</AnnualInterestRate>
<PIAmount>689.79</PIAmount>
<PaymentDueDate>2016-03-01</PaymentDueDate>
<CityTaxAmount>125.25</CityTaxAmount>
<CountyTaxAmount>666.22</CountyTaxAmount>
</PaymentChangeMaintenanceTransaction>
</PaymentChangeMaintenance>
Here is code someone wrote, but it is not clean-looking. I would like to use for-each :/
private void aggregateEscrowPaymountAmounts(List<PaymentChangeMaintenanceFieldsV214Type> fieldsType,
PaymentChangeMaintenance paymentChangeMaintenance, final int numberOfTrialPayments) {
AtomicInteger cnt = new AtomicInteger(1);
Iterator<PaymentChangeMaintenanceFieldsV214Type> fieldsTypeIterator = fieldsType.iterator();
PaymentChangeMaintenanceFieldsV214Type fieldType = fieldsTypeIterator.next();
PaymentChangeMaintenanceFieldsV214Type nextFieldType = null;
if (fieldsTypeIterator.hasNext()) {
nextFieldType = fieldsTypeIterator.next();
}
LocalDate monthDate = fieldType.getNextPaymentDueDate();
while (cnt.getAndIncrement() <= numberOfTrialPayments) {
PaymentChangeMaintenance tempPaymentChangeMaintenance = createPaymentChangeMaintenanceEscrow(fieldType);
paymentChangeMaintenance.aggregate(tempPaymentChangeMaintenance);
monthDate = monthDate.plusMonths(1);
if (nextFieldType != null) {
LocalDate nextFieldTypeDate = nextFieldType.getNextPaymentDueDate();
if (nextFieldTypeDate.getMonthValue() == monthDate.getMonthValue()) {
fieldType = nextFieldType;
if (fieldsTypeIterator.hasNext()) {
nextFieldType = fieldsTypeIterator.next();
} else {
nextFieldType = null;
}
}
}
}
}

For this certain case you can use a following approach: determine a step - for you it's a month. Then initialize a default value for a case of absence of the value on the next step. Then use some method that will take a next value and default value and depends on a step presence will return one of them
Here is a pseudocode:
List<Item> items;
Item nextItem = items.get(0);
Value step = month;
for (int i = 1; i < items.size(); i++) {
nextItem = getNextItem(items.get(i), nextItem, step);
****
}
Item getNextItem(Item nextItem, Item defaultItem, Value step) {
if (!nextItem.getStepValue().equals(calcNext(step))) {
return defaultItem;
} else {
return nextItem;
}
}
StepValue calcNext(Value step) {
/*some calculations. In your case month increment*/
}

Related

Is there a way to dynamically create a counter if such "month" exists?

I would like to enquire or get some reference as to how can I dynamically create a counter for each month if the exists ? Currently, I am retrieving the dates from a CSV file and store it in an ArrayList, from there I am comparing the dates to check whether if such month exists. If the month exists then "counter++". Afterwards, store the counter in a hashmap. I understand my code currently is an inefficient way of coding. How could I make it better ?
CODE
public HashMap<String, Integer> getDataPoint() {
//My function code
HashMap<String, Integer> numberOfPost = new HashMap<String, Integer>();
int janCounter = 0;
int febCounter = 0;
int marCounter = 0;
int aprCounter = 0;
int mayCounter = 0;
int juneCounter = 0;
int julyCounter = 0;
int augCounter = 0;
int septCounter = 0;
int octCounter = 0;
int novCounter = 0;
int decCounter = 0;
String pattern = "MMM";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
OpenCsvReader reader = new OpenCsvReader();
ArrayList <STPost> STArray = reader.loadST("file_path");
Iterator STitr = STArray.iterator();
while (STitr.hasNext()) {
STPost St = (STPost) STitr.next();
Date retrievedate = St.getTime();
String strDate = sdf.format(retrievedate);
if(strDate.equals("Jan")) {
janCounter++;
}
else if (strDate.equals("Feb")) {
febCounter++;
}
else if (strDate.equals("Mar")) {
marCounter++;
}
else if (strDate.equals("Apr")) {
aprCounter++;
}
else if (strDate.equals("May")) {
mayCounter++;
}
else if (strDate.equals("June")) {
juneCounter++;
}
else if (strDate.equals("July")) {
julyCounter++;
}
else if (strDate.equals("Aug")) {
augCounter++;
}
else if (strDate.equals("Sept")) {
septCounter++;
}
else if (strDate.equals("Oct")) {
octCounter++;
}
else if (strDate.equals("Nov")) {
novCounter++;
}
else if (strDate.equals("Dec")) {
decCounter++;
}
numberOfPost.put("January", janCounter);
numberOfPost.put("Feburary", febCounter);
numberOfPost.put("March", marCounter);
numberOfPost.put("April", aprCounter);
numberOfPost.put("May", mayCounter);
numberOfPost.put("June", juneCounter);
numberOfPost.put("July", julyCounter);
numberOfPost.put("August", augCounter);
numberOfPost.put("September", septCounter);
numberOfPost.put("October", octCounter);
numberOfPost.put("November", novCounter);
numberOfPost.put("December", decCounter);
}
return numberOfPost
}
You can create an array of months and check if value exists there using indexOf method.
String months = "JanFebMarAprMayJunJulAugSepOctNovDec";
Integer idx = months.indexOf(strDate);
Thereafter you can use SimpleDateFormat("MMMM") pattern to put and get it into your map.
if(idx > -1) {
String longDate = new SimpleDateFormat("MMMM").format(retrievedate);
Integer current = numberOfPost.get(longDate);
if (current == null) {
current = 1;
} else {
current += 1;
}
numberOfPost.put(longDate, current);
}
Thereafter, you can use map iterator to display content of map.
You already have a good start. Using a the hash map will make the code much tidier.
You can replace all those if statements and put statements with the code below:
if (!numberOfPosts.containsKey(strDate)) {
numberOfPosts.put(strDate, 0);
}
numberOfPosts.put(strDate, numberOfPosts.get(strDate) + 1);
The if statement will create a dictionary entry if there is not one with the key of strDate. The value of the entry is set to 0.
numberOfPosts.put(strDate, numberOfPosts.get(strDate) + 1)
The line above increments by 1 the dictionary entry with the key of strDate.

Observe livedata inside a for loop

I want to update a list in my activity that depends on the data of another list. Both the data list are being observed from the activity from the my viewmodel. After I get the data from my firstlist I need to run a for loop on this list to get the required ids and get the data for the second list.
But keeping the livedata observer in the for loop is causing a lot of problems. The for loop runs as expected but the livedata observer is getting called almost double the amount of the for loop. This happens only the first time when the list in being brought from the api. When I do the same operation a second time where the list is cached and is being brought from the database, the problem does not occur. Below is the source code for the problem,
for (int i = 0; i < firstList.size(); i++) {
final String uId = firstList.get(i).item.uid;
final long id = firstList.get(i).item.id;
viewModel.initAnotherItemRepository(uId, id);
viewModel.getSecondItem().observe(this, new Observer<Resource<List<SecondItem>>>() {
#Override
public void onChanged(Resource<List<SecondItem>> listResource) {
if (listResource.data != null) {
secondItemList.addAll(listResource.data);
if (count == firstList.size() - 1) {
//Do something
}
count = count + 1;
}
if (listResource.state == Resource.STATE_FAILURE) {
showLoadingSpinner(false);
}
}
}
);
}
Try to observe SecondItem outside the for loop. It gets data whenever update
viewModel.getSecondItem().observe(this, new Observer<Resource<List<SecondItem>>>() {
#Override
public void onChanged(Resource<List<SecondItem>> listResource) {
if (listResource.data != null) {
secondItemList.addAll(listResource.data);
if (count == firstList.size() - 1) {
//Do something
}
count = count + 1;
}
if (listResource.state == Resource.STATE_FAILURE) {
showLoadingSpinner(false);
}
}
}
);
for (int i = 0; i < firstList.size(); i++) {
final String uId = firstList.get(i).item.uid;
final long id = firstList.get(i).item.id;
viewModel.initAnotherItemRepository(uId, id);
}

Using a for-each loop to return largest value in arraylist

I'm having trouble writing a for-each loop that searches the arraylist and returns the county's name within the continent that has the highest gdp. Here's my code for it right now. (ElementsList is the original ArrayList)
public Country highestGdp(String continent) {
boolean flag;
for (Country cont : ElementsList) {
if (cont.getContinent().equals(continent)) {
ArrayList<Country> TMP1 = new ArrayList<Country>();
TMP1.add(cont);
for (Country gdp : TMP1) {
double max = 0;
if (max < gdp.getGDP()) {
max = gdp.getGDP();
}
if (gdp.getGDP() == max) {
ArrayList<Country> TMP2 = new ArrayList<Country>();
TMP2.add(gdp);
}
return gdp;
}
}
}
return null;
}
Each time you find a country in the right continent, you can check to see if it is greater than the max so far. Don't need to loop through all of them each time.
public Country highestGdp(String continent) {
boolean flag;
Country maxCountry = null;
for (Country cont : ElementsList) {
if (cont.getContinent().equals(continent)) {
if (maxCountry == null) maxCountry = cont;
if (maxCountry.getGDP() < gdp.getGDP()) {
maxCountry = cont;
}
}
}
return maxCountry;
}
Sorry for saying it but Your code is a little messy ;)
To shortly solve Your problem, try to move max declaration before the loop like this:
[...]
double max = 0;
for(Country gdp : TMP1){
[...]
We can see that TMP2 is completely useless, remove it:
// ArrayList<Country> TMP2 = new ArrayList<Country>();
// TMP2.add(gdp);
You create TMP1 list always with only 1 element and then iterate over it. This is also useless, You can do the code directly on the element You are adding to the list.
First iteration over ElementList is a list of Country elements, but the element You iterate is called cont (=continent) which is a Continent and not the Country. Is it intended to use Country class to cover both: Countries and Continents? Do You plan to have a tree structure like "Continents contains many Countries"?
Final code to solve problem from Your original question should be like this:
public Country highestGdp(String continent){
Country countryWithMaxGdp = null;
for(Country cont: ElementsList ){
if(cont.getContinent().equals(continent)){
if(countryWithMaxGdp == null || countryWithMaxGdp.getGDP() < cont.getGDP()){
countryWithMaxGdp = cont;
}
}
}
return countryWithMaxGdp;
}

HashMap only printing out last value in JTable row

I really tried searching for the solution to this problem, but I cant seem to get it right. I have an application that Im working on, and I would like to print out all of a customers orders in a JTable with rows. So if a customer has three orders I want it to show each order on a separate row.
With this code (the next block) I got it to work, but it's only printing out the last value. So if I have Order 3 attached to a customer, and then add Order 4, it only shows Order 4.
JButton btnHämtaKund = new JButton("Hämta");
btnHämtaKund.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String searchTerm = sökrutaKund.getText();
Customer c = Controller.findCustomer(searchTerm);
String sum = "";
if (c != null) {
if (c.getOrders() != null) {
for (Order tmp : c.getOrders().values()) {
String date = tmp.getDate();
String price = Double.toString(tmp.getPrice());
String rfd = "";
if (tmp.getRdyForDelivery() == true) {
rfd = "Ready for delivery";
} else if (tmp.getRdyForDelivery() == false) {
rfd = "Processing";
}
model.addRow(new String[] {date, price, rfd});
}
txtfieldTestKund.setText(sum);
} else {
txtfieldTestKund.setText("c.getOrders() == null");
}
} else {
txtfieldTestKund.setText("c == null");
}
}
});
Model is my DefaultModelTable.
I also tried with a for-loop like this in case I was overwriting my last row all the time:
for (int i = 0; i < c.getOrders().size(); i++) {
String date = c.getOrders().get(i).getDate();
String price = Double.toString(c.getOrders().get(i).getPrice());
String rfd = "";
if (c.getOrders().get(i).getRdyForDelivery() == true) {
rfd = "Ready for delivery";
} else if (c.getOrders().get(i).getRdyForDelivery() == false) {
rfd = "Processing";
}
Object row[] = {date, price, rfd};
model.addRow(row);
}
but that just gave a Nullpointerexception.
Any ideas what to do? Really thankful for help!
I had to fix a method to increase the key for each Order i added to Customer, looks like I was overwriting the previous with the last one.
private int counter = 0;
public void add(Order o) {
counter += 1;
String newCounter = Integer.toString(counter);
this.orders.put(newCounter, o);
}

In java How to merge two different size arraylist and make a new Arraylist?

I have two arraylist name preBusinessList, businessList. In business List I have data from server, and in preBusinessList is the local one. In lists I have id, count value Betterly demonstrate as below
Now I wanted to make a newBusinessList like this
How can I do it in java, please help me to solve this
Then I would use a map to do the merge using id as the key and convert it back to your list of (id,value) pairs
You can use:
Collections.sort(new ArrayList<...>(preBusinessList).addAll(businessList), comparator)
Where comparator is a class that implements Comparator interface (will be responsible for sorting as you wish)
assumming i understood your problem correctly (big if...):
also, i assume each element in the lists is a Pair - as it looks from your data (just a dumb wrapper class that holds 2 integers). if its some other class you'll need to adjust this code.
private Map<Integer,Integer> finalValues = new HashMap<Integer,Integer>();
for (Pair<Integer,Integer> entry : preBusinessList) {
finalValues.put(entry.getFirst(), entry.getSecond());
}
//2nd list overwrites values from 1st (anything not overwritten remains)
for (Pair<Integer,Integer> entry : businessList) {
finalValues.put(entry.getFirst(), entry.getSecond());
}
ArrayList<Pair<Integer,Integer>> finalList = new ArrayList<>();
for (Map.Entry<Integer,Integer> entry : finalValues) {
finalList.add(new Pair(entry.getKey(), entry.getValue());
}
//and now sort the list
Collections.sort(finalList, new Comparator<Pair<Integer,Integer>> {
int compare(Pair<Integer,Integer> a, Pair<Integer,Integer>b) {
return a.getFirst.compareTo(b.getFirst()); //compare by 1st number in pair only
}
});
Assuming something like:
public class Info {
public int id;
public int info;
}
You could merge them on the basis of wanting the keep the one with higher info field as follows:
// Assumes:
// - that the ArrayLists are sorted to have id in order going up
// - no repeated ids in a or in b (but same id can be in both a and b)
ArrayList<Info> merge(ArrayList<Info> a, ArrayList<Info> b) {
int aLength = a.size();
int bLength = b.size();
int ai = 0;
int bi = 0;
ArrayList<Info> result = new ArrayList<Info>();
while ((ai < aLength) && (bi < bLength))
Info aInfo = a.get(ai);
Info bInfo = b.get(bi);
if (aInfo.id == bInfo.id) {
if (aInfo.info >= bInfo.info) result.add(aInfo);
else result.add(bInfo);
ai++;
bi++;
}
else if (aInfo.id < bInfo.id) {
result.add(aInfo);
ai++;
}
else {
result.add(bInfo);
bi++;
}
}
// Add the remaining terms - only one of the loops will actually do anything
for (; ai<aiLength; ai++) {
result.add(a.get(ai));
}
for (; bi<biLength; bi++) {
result.add(b.get(bi));
}
}
Pseudocode :
Iterate over preBusinessList.
Fetch key and see if this key(1,2,3,4,5,6) exists in businesslist
If yes conitnue
Else If no, then add it to businesslist
for(Map.Entry<Integer, Integer> keyValue : preBusinessList.entrySet()) {
if(!businesslist.containsKey(keyValue.getKey())) {
businesslist.put(keyValue.getKey(), keyValue.getValue());
}
}
Updated Answer as per new requirements
boolean ifExists = false;
for(PlaceItems itemPreBusinessList : preBusinessList) {
ifExists = false;
for(PlaceItems itemBusinessList : businessList) {
if(itemBusinessList.businessId == itemPreBusinessList.businessId) {
// Already exists
ifExists = true;
break;
}
}
if(!isExists) {
businessList.add(itemPreBusinessList);
}
}

Categories

Resources