0

I have a class called Rating as follows:

import java.util.Date;

public class Rating implements Comparable<Rating> {

private long userId;
private long itemId;
private float ratingValue;
private Date dateTime;

public Rating(long userId, long itemId, float ratingValue, Date dateTime) {
    this.userId = userId;
    this.itemId = itemId;
    this.ratingValue = ratingValue;
    this.dateTime = dateTime;
}

@Override
public String toString() {
    return "Rating{" +
            "userId=" + userId +
            ", itemId=" + itemId +
            ", ratingValue=" + ratingValue +
            ", dateTime=" + dateTime +
            '}';
}

public Date getDateTime() {
    return dateTime;
}

public long getUserId() {
    return userId;
}

public void setUserId(long userId) {
    this.userId = userId;
}

public long getItemId() {
    return itemId;
}

public void setItemId(long itemId) {
    this.itemId = itemId;
}

public float getRatingValue() {
    return ratingValue;
}

public void setRatingValue(float ratingValue) {
    this.ratingValue = ratingValue;
}

public void setDateTime(Date datetime) {
    this.dateTime = datetime;
}

@Override
public int compareTo(Rating o) {
    return getDateTime().compareTo(o.getDateTime());
}

}

Now imagine I have a list called myList and it contains rating objects:

List<Rating> myList=New ArrayList<Object>();

Now I sort myList based on date:

Collections.sort(myList);

What I want to do is to find sublists of myList within some certain dates (for example ratings from April to May).

HimanAB
  • 2,443
  • 8
  • 29
  • 43

4 Answers4

1

I think you should use Unix time format to store time-stamp. You can use getime() function from Date class for conversion. If you sort on unix timestamp in ascending order you get the oldest date first. Hope this will help.

Anwar Shaikh
  • 1,591
  • 3
  • 22
  • 43
  • This was not my question. I know how to sort the list of objects that has date. My question was how to fetch a sublist of this list based on the date value of the objects in the sorted list. For example something like mylist.sublist.from(April, May) (This is a not a real code by the way) – HimanAB Jul 29 '16 at 17:26
  • 1
    Once you have date in unix time format all you have to do is find all the numbers in a range. For example, Dates between 1st April 2016 and 1st June 2016 will be all the numbers in range- (1459483200, 1464753600) – Anwar Shaikh Jul 29 '16 at 17:29
1

If you're on Java 8 (and you should be on Java 8 :>), use the streaming syntax:

result = myList.stream().filter(x -> x.getDateTime() != null && x.getDateTime().compareTo(earlierDate) >= 0 && x.getDateTime().compareTo(laterDate) <= 0).collect(Collectors.toList());

I assume you know how to construct earlierDate and laterDate.

Piotr Wilkin
  • 3,446
  • 10
  • 18
  • Also, a nice feature is that you can sort the result list on the fly by inserting `.sorted(yourComparator)` after `filter(...)`. – Piotr Wilkin Jul 29 '16 at 17:30
  • I actually don't know how to construct earlierDate and laterDate – HimanAB Jul 29 '16 at 17:32
  • Oops. Well, in that case, let me refer you to an answer: http://stackoverflow.com/questions/22326339/how-create-date-object-with-values-in-java – Piotr Wilkin Jul 29 '16 at 17:36
  • Might I suggest using `Date#after` and `Date#before` instead of `compareTo`? – bradimus Jul 29 '16 at 17:41
  • That might be a good idea, however, the problem is that `after()` and `before()` are exclusive, i.e. they do not include the exact date. You can use `!date.before(...)` and `!date.after(...)` for "not before" and "not after" respectively, but then the code is not necessarily clearer than with `compareTo()`. – Piotr Wilkin Jul 29 '16 at 17:41
0

You can try checking the range like this and adding it into sublist:

//Range values for date
    Date startDate=new Date("06/01/2007");
    Date endDate=new Date("07/01/2007");
    ArrayList<Rating> sublist=new ArrayList<Rating>();
    //check if list date comes in the range , If true add to sublist else not
    boolean result=false;
    for(int i=0;i<myList.size();i++)
    {
        result=!(myList.get(i).getDateTime().before(startDate) || myList.get(i).getDateTime().after(endDate));
        if(result)
            sublist.add(myList.get(i));

    }
    for(int i=0;i<sublist.size();i++)
    {
        System.out.println(sublist.get(i).toString());
    }
Rishal
  • 1,480
  • 1
  • 11
  • 19
0

You have a few options.

  1. If you have a list, sorted or not, you can build a sublist by traversing the list and selecting the elements that are in range. The sublist would be disconnected from the original list, and the operation would have to compare every element against the selection range.
    In Java 8, the process can be simplified using streams.

  2. If you have a sorted array (not list), you can perform a binary search of the range start and end values. You can then create a list from the subrange of the array. Again, the sublist would be disconnected from the original array, but the range lookup is faster (O(log(n)) vs O(n)).

  3. If you have a sorted list, you can find the range start and end positions by traversing the list, but stop (short-circuit) when reaching the end of the range, then use subList(). The sublist is then a view, so changes in either list is reflected in the other.

  4. If you don't actually need a sorted list, you can build a TreeMap<Date, Rating>, and call subMap(). Like option 3, it provides a view of the map.

Option 4 is likely the best if the list of rating can change.

Andreas
  • 154,647
  • 11
  • 152
  • 247