So I am developing a lost and found app using Fabric API. It has a option to sort the collected tweets based on user's current location. I found the below way online to sort using a comparator. This however, doesn't seem to work and the before-sorting and after-sorting results are totally alike.
public class SortLocations implements Comparator<Tweet> {
Double currLat;
Double currLng;
public SortLocations(Double currLat1, Double currLng1) {
currLat = currLat1;
currLng = currLng1;
}
@Override
public int compare(final Tweet tweet1, final Tweet tweet2) {
double lat1 = 0, lon1 = 0, lat2 = 0, lon2 = 0, distanceToPlace1 = 0, distanceToPlace2 = 0;
try {
lat1 = tweet1.coordinates.getLatitude();
lon1 = tweet1.coordinates.getLongitude();
lat2 = tweet2.coordinates.getLatitude();
lon2 = tweet2.coordinates.getLongitude();
distanceToPlace1 = distance(currLat, currLng, lat1, lon1);
distanceToPlace2 = distance(currLat, currLng, lat2, lon2);
} catch (Exception E) {
Log.d("No coordinates", "");
}
return (int) (distanceToPlace1 - distanceToPlace2);
}
public double distance(double fromLat, double fromLon, double toLat, double toLon) {
double radius = 6378137; // approximate Earth radius, *in meters*
double deltaLat = toLat - fromLat;
double deltaLon = toLon - fromLon;
double angle = 2 * Math.asin(Math.sqrt(
Math.pow(Math.sin(deltaLat / 2), 2) +
Math.cos(fromLat) * Math.cos(toLat) *
Math.pow(Math.sin(deltaLon / 2), 2)));
return radius * angle;
}
}
This is how the class is used in my activity
Collections.sort(tweetsSortedByLocation, new SortLocations(currLat, currLng));
Where tweetsSortedByLocation is of type List. Any help is really appreciated :)
I might suggest a slightly different approach that will make your life a little easier without losing any computation time.
Your current solution is likely n + n log(n) time: n for adding Tweets to the Collection, and then n log(n) for sorting. If you use a PriorityQueue (implemented as min-heap in Java) instead of a regular List (as I assume tweetsSortedByLocation is), then it'll sort as you add to it, giving you n log(n) time: n for each element and log(n) for each insertion (think binary search).
You can use a PriorityQueue like so (https://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html):
PriorityQueue<Tweet> tweetsSortedByLocation = new PriorityQueue<>(10, new SortLocations(currLat, currLong));
tweetsSortedByLocation.add(new Tweet()); // Or however you add them now
You could also inline the Comparator, but using SortLocations is better.
Now as to why nothing changes when you sort, that means compare() must be returning 0 every time. That would happen if the difference between the two distances you calculate is less than 1. Look at the integer cast on this line:
return (int) (distanceToPlace1 - distanceToPlace2);
If distanceToPlace1 and distanceToPlace2 are no more than 1 in difference, that integer cast brings it to 0, which, in how compare must be implemented, means equality. (See https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html.) So, try this instead (to sort least distance first (i.e. asc by distance)):
if (distanceToPlace1 < distanceToPlace2) {
return -1;
} else if (distanceToPlace1 > distanceToPlace2) {
return 1;
} else {
return 0;
}
I hope that fixes your problem