How to Sort Arraylist of Objects by Timestamp and Get Last Five Elements

How to sort ArrayList of objects by timestamp and get last five elements

I see 3 places to improve slightly:

  1. Don't scan chatMessages twice (contains and indexOf):

    int pos = chatMessages.indexOf(chatMessage);
    if (pos == -1) {
    chatMessages.add(chatMessage);
    } else {
    chatMessages.set(pos, chatMessage);
    }
  2. Use Timestamp.compareTo:

    Collections.sort(chatMessages, new Comparator<ChatMessage>() {
    @Override
    public int compare(ChatMessage o1, ChatMessage o2) {
    return o1.getTimestamp().compareTo(o2.getTimestamp());
    }
    });

    In Java 8+:

    Collections.sort(chatMessages, Comparator.comparing(ChatMessage::getTimestamp));
  3. Use ArrayList.addAll:

    finalChatMessages.clear();
    finalChatMessages.addAll(chatMessages.subList(Math.max(chatMessages.size() - 5, 0), chatMessages.size()));

Sort objects in ArrayList by date?

You can make your object comparable:

public static class MyObject implements Comparable<MyObject> {

private Date dateTime;

public Date getDateTime() {
return dateTime;
}

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

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

And then you sort it by calling:

Collections.sort(myList);

However sometimes you don't want to change your model, like when you want to sort on several different properties. In that case, you can create comparator on the fly:

Collections.sort(myList, new Comparator<MyObject>() {
public int compare(MyObject o1, MyObject o2) {
return o1.getDateTime().compareTo(o2.getDateTime());
}
});

However, the above works only if you're certain that dateTime is not null at the time of comparison. It's wise to handle null as well to avoid NullPointerExceptions:

public static class MyObject implements Comparable<MyObject> {

private Date dateTime;

public Date getDateTime() {
return dateTime;
}

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

@Override
public int compareTo(MyObject o) {
if (getDateTime() == null || o.getDateTime() == null)
return 0;
return getDateTime().compareTo(o.getDateTime());
}
}

Or in the second example:

Collections.sort(myList, new Comparator<MyObject>() {
public int compare(MyObject o1, MyObject o2) {
if (o1.getDateTime() == null || o2.getDateTime() == null)
return 0;
return o1.getDateTime().compareTo(o2.getDateTime());
}
});

Sort objects by timestamp, but then group dependencies

Brute force non-working approach - one option to perform sorting in one single operation you would need to make parent part of sort key in a following way and than sort by {order(Node.Parent), timestamp(Node)} pairs using any algorithm you like.

  • "A is parent of B" => "order(A) < order(B)" and
  • "C.timestamp < D.timestamp" => order(C) < order(D)

Unfortunately this "order" function requires sorting of all child nodes first to satisfy second condition thus breaking "one sort" requirement.


To get single sort you can use composite key that includes timestamps for all parent nodes and then sort by such composite key.

The easiest way to build composite key is to construct tree based on parent objects and set value of the key to be concatenation of parent's key and own timestamp using any tree traversal.

Sample:

  • Data

    A (ts = 5) parent of B (ts = 7),C (ts = 2)
    B parent of D (ts = 3)
  • Building tree:

    A -> B -> D  
    -> C
  • Pre-order traversal: A, B, D, C

  • composite key -

    A -> A.timestamp = 5
    B -> key(A) concat B.timestamp = 5.7
    C -> key(A) concat C.timestamp = 5.2
    D -> key(B) concat D.timestamp = 5.7.2

  • data for sorting by {order, timestamp} pairs

     A {order(no-parent), ts} = {0, 5}
    B {order(A), ts} = {1,7}
    C {1,2}
    D {2,3}
  • sorted sequences - {5}, {5.2},{5.7},{5.7.2} mapping back to nodes - A,C,B,D

Complexity of this approach is O(n log(n) max_depth):

  • build tree/walk tree/build keys - O(n)
  • sort is complexity of sort (usually O(num_elm log(num_elem)) multiplied by complexity of comparing keys which are depending on depth of parent-child tree. This part dominates O(n) needed for preparation phase.

Alternatively you can just build tree, sort each level by time-stamp and than put them back in a list via pre-order traversal, which removes complexity of key comparison but breaks requirement of single sort.

Sort List<Object> by current month to Last six months

Here's how I would do it:

enum Month {
JANUARY,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
OCTOBER,
NOVEMBER,
DECEMBER
}
public static void main(String[] args) {
List<String> data = Arrays.asList("october", "april", "march", "november", "may", "january", "december");
Month currentMonth = Month.MAY;
List<String> thisYear = data.stream()
.filter(a -> Month.valueOf(a.toUpperCase()).ordinal() <= currentMonth.ordinal())
.collect(Collectors.toList());
List<String> lastYear = data.stream()
.filter(a -> Month.valueOf(a.toUpperCase()).ordinal() > currentMonth.ordinal())
.collect(Collectors.toList());
Comparator<String> monthComparator = new Comparator<String>() {

@Override
public int compare(String a, String b) {
Month mA = Month.valueOf(a.toUpperCase());
Month mB = Month.valueOf(b.toUpperCase());
return mB.compareTo(mA);
}
};
thisYear.sort(monthComparator);
lastYear.sort(monthComparator);

thisYear.addAll(lastYear);
System.out.println(thisYear);
}

Sort a List by a date present in another list

I'd recommend you convert list of ObjectB into a Map<id, createdOn> as retrieving elements by key is O(1) in Map but O(n) in List.

Map<Integer, Timestamp> createdOnMap =
bList.stream().collect(Collectors.toMap(ObjectB::getId, ObjectB::getCreatedOn));

Then compare by getting the value of this map, and if it's not present decide whether to place it as first or last in the list by comparing the value against a maximum/minimum value. An example with LocalDateTime:

aList.stream()
.sorted(Comparator.comparing(objectA -> createdOnMap.getOrDefault(objectA.getId(), LocalDateTime.MAX)))
.collect(Collectors.toList())

In the scenario that createdOnMap doesn't have a value for this id, it compares against LocalDateTime.MAX/MIN.

If you also want to have in the final list elements that are not present in List but are in List, then you'll need to add those elements by yourself before sorting by converting ObjectB to ObjectA.

Sort and merge two Arraylist of user defined type Library class

I would suggest creating a holder class, that holds an OSD object, which in turns implements Comparable

public class OSDHolder implements Comparable<OSDHolder> {

private final OSD obj;

public OSDHolder(OSD obj) {
this.obj = obj;
}

public long getTiming() {
this.obj.getUpdatedOn().getTime();
}

@Override
public int compareTo(OSDHolder o) {
if (this.getTiming() > o.getTiming())
return 1;
else if (this.getTiming < o.getTiming())
return -1;
return 0;
}
}

Then you can simply add the contents of both lists to one list as OSDHolder type

ArrayList<OSDHolder> holders = new ArrayList<>();

for (OSD osd:awbThingTypeOSDs) {
holders.add(new OSDHolder(osd));
}

for (OSD osd:LDDthingTypeOSDs) {
holders.add(new OSDHolder(osd));
}

Then sort holders with either Collections.sort() or Arrays.sort()

Sort array of objects with date field by date

You don't really need lodash. You can use JavaScript's Array.prototype.sort method.

You'll need to create Date objects from your date strings before you can compare them.

var myArray = [{  name: "Joe Blow",  date: "Mon Oct 31 2016 00:00:00 GMT-0700 (PDT)"}, {  name: "Sam Snead",  date: "Sun Oct 30 2016 00:00:00 GMT-0700 (PDT)"}, {  name: "John Smith",  date: "Sat Oct 29 2016 00:00:00 GMT-0700 (PDT)"}];
myArray.sort(function compare(a, b) { var dateA = new Date(a.date); var dateB = new Date(b.date); return dateA - dateB;});
console.log(myArray);

How to sort/order a list by date in dart/flutter?

In your example above, expiry is a String, not a DateTime object. You have a few options here, depending on what you want to achieve.

The easiest solution would be to use String's built in compareTo method, which allows sorting Strings. Those timestamps are already in a sortable format, so this would work:

products.sort((a,b) {
return a.compareTo(b);
});

Or more concise:

products.sort((a,b) => a.compareTo(b));

This is pretty basic. Like pskink mentioned in the comment, building on this you could convert the Strings to actual DateTime objects.

DateTime expiryAsDateTime = DateTime.parse(expiry);

DateTime also has a built in compareTo method, so the code snippet above would work with DateTimes as well as Strings.

If you want to reverse the order, just swap a and b.

Sort Objects in Array by date

Using Swift 4 & Swift 3

let testArray = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", "2 Jul, 2016"]
var convertedArray: [Date] = []

var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MM, yyyy"// yyyy-MM-dd"

for dat in testArray {
let date = dateFormatter.date(from: dat)
if let date = date {
convertedArray.append(date)
}
}

var ready = convertedArray.sorted(by: { $0.compare($1) == .orderedDescending })

print(ready)

Using Swift 2

For example you have the array with dates and another 1 array, where you will save the converted dates:

var testArray = ["25 Jun, 2016", "30 Jun, 2016", "28 Jun, 2016", "2 Jul, 2016"]
var convertedArray: [NSDate] = []

After that we convert the dates:

var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "dd MM, yyyy"// yyyy-MM-dd"

for dat in testArray {
var date = dateFormatter.dateFromString(dat)
convertedArray.append(date!)
}

And the result:

var ready = convertedArray.sort({ $0.compare($1) == .OrderedDescending })

print(ready)


Related Topics



Leave a reply



Submit