I am making an app in Android Studio using Java, that is recieving data from my RestApi. I get the data in a List with objects "Payment" containg a date and an amount.
The idea is to add the amount from the same date and put it into a data entry for a graph that is then displayed on the app. I'm using AnyChart for the graph.
I'm unsure on how to compare the dates, and from there add together the amount for one data entry for that specific date. The goal is to be able to pick the interval in which you want the data presented. Wether it's the last week, month, 6 months etc.
The payment class
public class Payment {
private String id;
private Long amount;
private Date date;
private String email;
private String name;
public Payment(String id, Long amount, Date date, String email, String name) {
this.id = id;
this.amount = amount;
this.date = date;
this.email = email;
this.name = name;
}}
To make the call from the app to my backend I use retrofit. The code below is how i imagine it would look like
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AnyChartView anyChartView = (AnyChartView) findViewById(R.id.any_chart_view);
List<DataEntry> seriesData = new ArrayList<>();
Cartesian cartesian = AnyChart.line();
Call<List<Payment>> call = RetrofitClient
.getInstance()
.getAPI()
.getPayment(new PaymentRequest("30"));
call.enqueue(new Callback<List<Payment>>() {
@Override
public void onResponse(@NonNull Call<List<Payment>> call,
@NonNull Response<List<Payment>> response) {
List<Payment> payments = response.body();
if (payments != null) {
for (int i = 0; i < payments.size(); i ) {
// If the date of the next index in the list is //the same as current
//date add the amount together.
//If not add a new data entry to seriesData //with date eg. 31/08 and
//the total amount from that date
}
}
}
@Override
public void onFailure(@NonNull Call<List<Payment>> call,
@NonNull Throwable t) {
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
}
});
cartesian.data(seriesData);
anyChartView.setChart(cartesian);
}}
I cannot seem to find or google a solution to the problem above, or maybe I am on the wrong path.
I've tried something like
seriesData.add(new ValueDataEntry(payments.get(i).getDate().toString(),
payments.get(i).getAmount()));
But that makes a new entry for every single index in the List. Solutions I've come across seems to compare dates including the time, but in this instance only I need the date, the time does not matter, so the data entry could look something like
seriesData.add(new ValueDataEntry("31/08", totaled amount from that date));
I hope the above make sense.
Edit: I think i've missed important information. This is the only part of the project where the time doesn't matter. Other parts of the project need both the date and time. I've taken note, and changed away from Date to LocalDateTime.
CodePudding user response:
You can use a hashmap for this logic. Use date as key and amount as value.
HashMap<String, Double> paymentMap = new HashMap<>();
if (paymentMap.contains(date)) {
paymentMap.put(date, amount paymentMap.get(date));
}
else {
paymentMap.put(date, amount);
}
CodePudding user response:
Others have alluded to the use of LocalDate and a HashMap. You can also use LocalDate as the key in your Map. Moreover, if you use a TreeMap instead of a HashMap, it will keep the dates in ascending order (from the earliest date to the latest date). Here's a minimal example:
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Payment {
private final String id;
private final Long amount;
private final LocalDate date;
private final String email;
private final String name;
public Payment(String id, Long amount, LocalDate date, String email, String name) {
this.id = id;
this.amount = amount;
this.date = date;
this.email = email;
this.name = name;
}
public Long getAmount() {
return amount;
}
public LocalDate getDate() {
return date;
}
public static void main(String[] args) {
List<Payment> payments = List.of(
new Payment("1", 10L, LocalDate.of(2022, 9, 13), "[email protected]", "name"),
new Payment("2", 20L, LocalDate.of(2022, 9, 13), "[email protected]", "name"),
new Payment("3", 30L, LocalDate.of(2022, 9, 14), "[email protected]", "name"),
new Payment("4", 40L, LocalDate.of(2022, 9, 15), "[email protected]", "name"),
new Payment("5", 50L, LocalDate.of(2022, 9, 15), "[email protected]", "name"));
Map<LocalDate, Long> dailyTotals = new TreeMap<>();
for (Payment payment : payments) {
LocalDate date = payment.getDate();
if (dailyTotals.containsKey(date)) {
dailyTotals.put(date, payment.getAmount() dailyTotals.get(date));
} else {
dailyTotals.put(date, payment.getAmount());
}
}
}
}
In the end, the value of dailyTotals
is
"2022-09-13" -> 30
"2022-09-14" -> 30
"2022-09-15" -> 90
Finally, iterate/stream over the entrySet in dailyTotals
and add them to your seriesData object.
dailyTotals.entrySet().stream()
.map(entry -> new ValueDataEntry(entry.getKey().toString(), entry.getValue()))
.forEach(seriesData::add);