Removing element from ArrayList<HashMap<String, String>> - android

Hi I have this array list of hashmaps
[{EndTime=09:00 AM, UserId=48, StartTime=08:00 AM, AppointmentId=79, Date=11/18/13},
{EndTime=09:00 AM, UserId=48, StartTime=08:00 AM, AppointmentId=80, Date=11/18/13},
{EndTime=09:00 AM, UserId=48, StartTime=08:00 AM, AppointmentId=81, Date=11/18/13},
{EndTime=09:00 AM, UserId=48, StartTime=08:00 AM, AppointmentId=82, Date=11/18/13},
{EndTime=09:00 AM, UserId=48, StartTime=08:00 AM, AppointmentId=83, Date=11/18/13},
{EndTime=09:00 AM, UserId=48, StartTime=08:00 AM, AppointmentId=85, Date=11/18/13}]
I want to check particular entry from here using "AppoinmentID" and i want to get that record for a diferent hashmap and all the others to a different one.. how can I do it? Thanks in advance.

storing these values in a hashmap is not a good idea. why don't you create an appointment class. removing an appointment object will be easy in this case.
public class Appointment
{
private int appointmentId;
private int userId; // or private User user
private Date start;
private Date end;
public Appointment(int id)
{
this.appointmentId = id;
}
// getters and setters
#Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (this.getClass() != obj.getClass())
{
return false;
}
Appointment other = (Appointment) obj;
if (this.appointmentId != other.appointmentId)
{
return false;
}
return true;
}
}
now if you want to delete a specific item with a certain ID:
List<Appointment> appointments = new ArrayList<Appointment>();
appointments.remove(new Appointment(theIdYouWantToDelete));
or an even better way:
Store them like this
Map<Integer, Appointment> appointments = new HashMap<Integer, Appointment>();
appointments.put(appointment.getAppointmentId(), appointment);
and remove them like this:
appointments.remove(theIdYouWantToDelete);
with this approach, you do not need the equals method.
Why it works:
When you want to remove an Object from a List or a Map, Java uses the equals method to identify them. As You can see i only check for the appointmentId. So if the IDs of 2 object are the same, Java says they are the same object. If you don't override equals, check only checks for == (same object in the memory) which mostly isn't the case.

1.Create a class
public class Appointment
{
public int appointmentId;
public int userId;
public Date startTime;
public Date endTime;
public Appointment(int id,int aUserID,Date aStartTime,Date aEndTime)
{
this.appointmentId = id;
this.userId = aUserID;
this.startTime = aStartTime;
thiis.endTime = aEndTime;
}
}
2. Creating Appointment Object and Storing in HashMap
String dateFormat = "MMMM d, yyyy HH:mm"; //any date format
DateFormat df = new SimpleDateFormat(dateFormat);
Date startDate = df.parse("January 2, 2010 13:00");
Date endDate = df.parse("January 2, 2010 20:00");
Appointment appointment1 = new Appointment(1,23,startDate,endDate);
...
Map<Integer, Appointment> appointments = new HashMap<Integer, Appointment>();
// add to hashmap making appointment id as key
appointments.put(appointment1.appointmentId,appointment1);
......
...
appointments.put(appointmentN.appointmentId,appointmentN);
3. deleting an Appointment Object
appointments.remove(aAppointmentId)
4. getting an Appointment Object
Appointment ap = appointments.get(aAppointmentId);
System.out.printLn("id "+ ap.appointmentId);
System.out.printLn("userId "+ ap.userId);
DateFormat df = new SimpleDateFormat(dateFormat);
System.out.printLn("starttime "+ df.format(ap.startTime));
System.out.printLn("endtime "+ df.format(ap.endTime));

You can have class:
public class Apointment{
Stirng EndTime="09:00 AM";
int AppointmentId=79;
...
...
}
and have one hashmap with apointmentId as key
HashMap<Integer,Apointment> map=new HashMap<Integer,Apointment>();
Apointment ap=new Apointment(...);
map.put(ap.getAppointmentId(),ap);
..
..
..
And if you have apointmentID you can get apointment object by:
Apointment ap=map.get(79);

Related

Android Room with RxJava: get data from Room with the loop

I am new for using RxJava and Room. What I trying to do is run a for loop to get data from database. The for loop iterate from first day of month to the last day of month.
Here is the Dao for this query.
#Query("SELECT SUM(duration) FROM xxx WHERE timeStamp >= :start and timeStamp <= :end and userId = :userId")
Flowable<Integer> getDuration(String userId, long start, long end);
And Here is how i using RxJava to get the result.
Calendar day1 = Calendar.getInstance();
Calendar day2 = Calendar.getInstance();
int maxLoopIndex = day1.getActualMaximum(Calendar.DAY_OF_MONTH);
day1.setFirstDayOfWeek(Calendar.MONDAY);
day2.setFirstDayOfWeek(Calendar.MONDAY);
day1.set(Calendar.DATE, day1.getActualMinimum(Calendar.DATE));
day2.set(Calendar.DATE, day2.getActualMinimum(Calendar.DATE));
day1.set(Calendar.HOUR_OF_DAY, 0);
day1.set(Calendar.MINUTE, 0);
day1.set(Calendar.SECOND, 0);
day1.set(Calendar.MILLISECOND, 0);
day2.set(Calendar.HOUR_OF_DAY, 23);
day2.set(Calendar.MINUTE, 59);
day2.set(Calendar.SECOND, 59);
day2.set(Calendar.MILLISECOND, 999);
ArrayList<Pair<Long, Long>> maxDayCount = new ArrayList<>();
//Get all the timeStamp in a month, where maxDayCount can be 30, 31, 28, 29.
for (int i = 0; i < maxDayCount; i++) {
Pair<Long, Long> P = Pair.create(day1.getTimeInMillis(), day2.getTimeInMillis());
pairArrayList.add(P);
day1.add(Calendar.DATE, 1);
day2.add(Calendar.DATE, 1);
}
// Using Flowable.formIterable to run through the list and get the data from room
Flowable.fromIterable(pairArrayList)
.flatMap(new Function<Pair<Long, Long>, Flowable<Integer>>() {
#Override
public Flowable<Integer> apply(#NonNull Pair<Long, Long> date) throws Exception {
return roomdb.Dao().getDuration(
User.getCurUser().getId(), date.first, date.second
);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
#Override
public void accept(#NonNull Integer source) throws Exception {
Log.d(TAG, "Duration: "+source);
// I want to get the index of pairArrayList to store the duration in
// corresponding array
}
});
However in subscribe I can get the result return by room however I can not get which index is run in pairArrayList. Is there any way I can get the index? Furthermore is there any better way to get data from room with the loop?
Let's begin with the final structure. It should contain the day of month and duration:
class DayDuration {
public Integer day;
public Long duration;
public DayDuration(Integer day, Long duration) {
this.day = day;
this.duration = duration;
}
#Override
public boolean equals(Object o) { /* implementation */ }
#Override
public int hashCode() { /* implementation */ }
}
Creation of final Flowable what emits requested items might look like the following code. I have used ThreetenBP library to handle date/time operations because Android Calendar API is pure hell. Recommend you do the same:
class SO64870062 {
private Flowable<Long> getDuration(String userId, long start, long end) {
return Flowable.fromCallable(() -> start); // mock data
}
#NotNull
private Flowable<LocalDate> getDaysInMonth(YearMonth yearMonth) { // (1)
LocalDate start = LocalDate.of(yearMonth.getYear(), yearMonth.getMonthValue(), 1);
LocalDate end = start.with(TemporalAdjusters.lastDayOfMonth());
return Flowable.create(emitter -> {
LocalDate current = start;
while (!current.isAfter(end)) { // (2)
emitter.onNext(current);
current = current.plusDays(1);
}
emitter.onComplete();
}, BackpressureStrategy.BUFFER);
}
#NotNull
private Flowable<DayDuration> getDurationForDay(String userId, LocalDate localDate) {
long startDayMillis = localDate.atStartOfDay().atZone(ZoneOffset.UTC) // (3)
.toInstant()
.toEpochMilli();
long endDayMillis = localDate.atTime(LocalTime.MAX).atZone(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
return getDuration(userId, startDayMillis, endDayMillis) // (4)
.map(duration -> new DayDuration(localDate.getDayOfMonth(), duration));
}
public Flowable<DayDuration> getDayDurations(String userId, YearMonth yearMonth) {
return getDaysInMonth(yearMonth)
.flatMap(localDate -> getDurationForDay(userId, localDate));
}
}
Important and interesting parts:
Function getDaysInMonth() creates Flowable what emits all days of requested month.
Iteration from start (first day of a month) to end (last day of a month) date and emitting all of the days.
Make sure you set the zone you use within timestamps in your database. I have used UTC for simplicity.
Combine duration from a database with the current date.
Last but not least, let's check if it works correctly:
public class SO64870062Test {
#Test
public void whenDaysRequestedForApril2020ThenEmitted() {
SO64870062 tested = new SO64870062();
TestSubscriber<DayDuration> testSubscriber = tested
.getDayDurations("userId", YearMonth.of(2020, 11))
.test();
testSubscriber.assertValueCount(30);
testSubscriber.assertValueAt(1, new DayDuration(2, 1604275200000L));
testSubscriber.assertComplete();
}
}

How to serialize a json firestore Timestamp to Date?

I store a Date in Firestore. I get an HashMap<String, Object> from firestore and i want to recreate my object from it.
Before implementing the Date the working code was :
HashMap<String, Object> document = new HashMap<String, Object>();
document.put("name", "name");
JSONElement jsonElement = gson.toJsonTree(document);
Event event = gson.fromJson(jsonElement , Event.class);
I have now add the field
#ServerTimestamp
private Date dateOfEvent;
But when i try to serialize it i get the following error:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected STRING but was BEGIN_OBJECT at path $.dateOfEvent
Because the JsonElement "dateOfEvent" look like this because it's a Firestore Timestamp:
{"dateOfEvent": {"nanoseconds":0,"seconds":1584921600}, "name": "test Event"}
Thanks for your time and your help.
Gson is expecting a Date string like 2020-02-27T09:00:00 but it's actually an object. You could setup your classes like this and add a helper method to get dateOfEvent as a Date:
class Event {
private String name;
private MyDate date;
}
class MyDate {
private Long nanoseconds;
private Long seconds;
// getters/setters for nanoseconds, seconds...
public Date asDate() {
// convert to date
}
}

RxJava2 emit items in order

I'm making a exchange rate app and I have a screen with a graph that shows changes of the selected currency in the last 7 days.
Now what I wanna get is to emit items in strict order.
Here is my code:
public class GraphInteractorImpl implements GraphInteractor {
private final Retrofit retrofit;
#Inject
public GraphInteractorImpl(Retrofit retrofit) {
this.retrofit = retrofit;
}
#Override
public void downloadData(GraphListener listener) {
RestAPI api = retrofit.create(RestAPI.class);
List<String> listDates = getDates();
for (String date : listDates) {
Observable<List<ExchangeRate>> observable = api.getExchangeRatesForLast7days(date);
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
listener::onSuccess,
listener::onFailure
);
}
}
private List<String> getDates() { //returns last 7 days in a list
List<String> listDate = new ArrayList<>();
Calendar calendarToday = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
String today = simpleDateFormat.format(calendarToday.getTime());
Calendar calendarDayBefore = Calendar.getInstance();
calendarDayBefore.setTime(calendarDayBefore.getTime());
int daysCounter = 0;
while (daysCounter <= 7) {
if (daysCounter == 0) { // means that its present day
listDate.add(today);
} else { // subtracts 1 day after each pass
calendarDayBefore.add(Calendar.DAY_OF_MONTH, -1);
Date dateMinusOneDay = calendarDayBefore.getTime();
String oneDayAgo = simpleDateFormat.format(dateMinusOneDay);
listDate.add(oneDayAgo);
}
daysCounter++;
}
return listDate;
}
}
This code gets me the right values but they are not in order so I'm getting wrong values for specific days.
So what I have to do is execute 7 calls simultaneously, I'm guessing with zip operator but I didnt come up with a solution for this yet so any type of help would be appreciated.
API docs can be found here: http://hnbex.eu/api/v1/
So what I did to solve this is I added all the 7 observables in a list and then I just called the zipIterable() on that list

Android - MPAndroidChart LineChart, not able to plot according to value date

I am using MPAndroidChart for my line chart.
I have date values and score values.
Example: on 11/10/2016 my score was 45.
I am struggling with the dates. Not sure how to set it in my setYAxisValues.
I am getting my values from a rest api and putting it in the graph.
This part is where i have my problem.
yVals.add(new Entry(Float.valueOf(ocd.getScore()), foo));
If I change foo to a normal int value like 1, 2, 3 I have no problem. The graph is working. The issue, i need to use dates to plot my value at the correct place.
#Override
protected void onPostExecute(List<ResultModel> result) {
super.onPostExecute(result);
//populating my yAxis with values from rest
for (ResultModel ocd : resModelList){
long unixSeconds = Long.parseLong(ocd.getPost_date());
Date date = new Date(unixSeconds*1000L);
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
String formattedDate = sdf.format(date);
int foo = Integer.parseInt(formattedDate);
yVals.add(new Entry(Float.valueOf(ocd.getScore()), foo));
}
}
The X axis is working
//set vales
private ArrayList<String> setXAxisValues(){
xVals = new ArrayList<String>();
//MM/dd/yyyy
xVals.add("01/01/2016");
xVals.add("02/01/2016");
xVals.add("03/01/2016");
xVals.add("04/01/2016");
xVals.add("05/01/2016");
return xVals;
}
private ArrayList<Entry> setYAxisValues(){
yVals = new ArrayList<Entry>();
return yVals;
}
Thanks in advance
I had the similar issue, the point is - MPChart library cannot have anything but float for X axis. I'd suggest you to have X axis represented by date's millis. Suppose you have four values with dates "01/01/2016", "02/01/2016", "03/01/2016", "04/01/2016", "05/01/2016". You add values like
yVals.add(new Entry(Float.valueOf(ocd.getScore()), "01/01/2016".toMillis()));
"01/01/2016".toMillis() is pseudocode of course, you need to convert your date to int (float).
Then, set up minX as "01/01/2016".toMillis(), maxX as"04/01/2016".toMillis(),
and provide a label formater which will format this millis back to string dates:
private class LabelFormatter implements AxisValueFormatter {
private Context context;
private LabelFormatter(Context context) {
this.context = context;
}
#Override
public int getDecimalDigits() {
return -1;
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
return DateUtils.formatDateTime(context, (long) value, DateUtils.FORMAT_SHOW_DATE);
}
}

Android: How can i sort HashMap by values from two sources?

I have created a records based on date, name and url from default browser and google chrome. I combine the history information based on the two browser and display it using Hashmap. So now what i am trying to do is I would like to do a sort by date and also by name. However, due to my knowledge i am facing difficulties implementing it. Any advice and suggestions will be greatly appreciated. Thank you in advance.
//default browser
if (mCur.moveToFirst() && mCur.getCount() > 0) {
int titleIdx = mCur.getColumnIndex(Browser.BookmarkColumns.TITLE);
int urlIdx = mCur.getColumnIndex(Browser.BookmarkColumns.URL);
int dateIdx = mCur.getColumnIndex(Browser.BookmarkColumns.DATE);
while (mCur.isAfterLast() == false) {
HashMap temp = new HashMap();
temp.put(FIRST_COLUMN,getDate(mCur.getLong(dateIdx), "dd/MM/yyyy HH:mm:ss "));
temp.put(SECOND_COLUMN, mCur.getString(titleIdx));
temp.put(THIRD_COLUMN, mCur.getString(urlIdx));
list.add(temp);
mCur.moveToNext();
}
}
//google chrome
if (mCur2.moveToFirst() && mCur2.getCount() > 0) {
int dateIdx2 = mCur2.getColumnIndex(Browser.BookmarkColumns.DATE);
int titleIdx2 = mCur2.getColumnIndex(Browser.BookmarkColumns.TITLE);
int urlIdx2 = mCur2.getColumnIndex(Browser.BookmarkColumns.URL);
while (mCur2.isAfterLast() == false) {
HashMap temp = new HashMap();
temp.put(FIRST_COLUMN, getDate(mCur2.getLong(dateIdx2), "dd/MM/yyyy HH:mm:ss "));
temp.put(SECOND_COLUMN, mCur2.getString(titleIdx2));
temp.put(THIRD_COLUMN, mCur2.getString(urlIdx2));
list.add(temp);
mCur2.moveToNext();
}
}
Create a Model class for your data with sorting comparators like below:
public class MyItem {
String title;
String url;
String date;
public MyItem(String title, String url, String date) {
this.title = title;
this.url = url;
this.date = date;
}
public static Comparator<MyItem> sortByDate = new Comparator<MyItem>() {
#Override
public int compare(MyItem item1, MyItem item2) {
return item1.date.compareTo(item2.date);
}
};
public static Comparator<MyItem> sortByTitle = new Comparator<MyItem>() {
#Override
public int compare(MyItem item1, MyItem item2) {
return item1.title.compareTo(item2.title);
}
};
}
Then use it like this in your code
Create a list/array of Myitems
then call the function to sort => Arrays.sort(yourMyItemsObject, MyItem.sortByTitle);
Change the code of compare() Method as per your need of sort.
Use Inner class concept for sorting the hash map, dont use two hash map,
First sort the hash map of class level and then sort the hash value, by this in the same hash map you will get the both sorted value
Look at Sortable HashMap-like data structure in Java? for using sortable HashMap like data structures.
You'll need to combine all data into one Map object and then sort it just before you want to display the result to the user.
good luck

Categories

Resources