Sorting a List of Points with Java

Efficient way of sorting a ListPoint by X value

I assume you are talking about class java.awt.Point,
thus having a getX() method.

Using Java 8 you can sort points by x:

List<Point> points = ...;
points.sort(Comparator.comparing(Point::getX));

In lower versions of Java, such as 7, you can implement the Comparator to achieve this:

List<Point> points = ...;
Collections.sort(points, new Comparator<Point>() {
@Override
public int compare(Point p1, Point p2) {
return Double.compare(p1.getX(), p2.getX());
}
});

Java how to sort an ArrayList of Point objects

You were close. The problem you had was simply that you invoked

  public void sortByXCoordinates(){

coordinateList.sort(coordinates, new PointCompare());

}

What you want is this:

import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import javax.swing.JOptionPane;

public class MainClass {

private final Point coordinates = new Point(0, 0);
private final int MAX_POINTS = 3;
private final ArrayList<Point> coordinateList = new ArrayList<Point>();

public void inputCoordinates() {

String tempString;
int tempx = 0;
int tempy = 0;

for (int i = 0; i < this.MAX_POINTS; i++) {
try {
tempString = JOptionPane.showInputDialog(null, "Enter X coordinate:");
tempx = Integer.parseInt(tempString);
tempString = JOptionPane.showInputDialog(null, "Enter Y coordinate:");
tempy = Integer.parseInt(tempString);
this.coordinates.setLocation(tempx, tempy);// set input data into
this.coordinateList.add(this.coordinates.getLocation()); // put in
}
catch (final NumberFormatException e) {
System.err.println("ERROR!");
main(null);

}
}
}

public void displayPoints() {

for (int i = 0; i < this.MAX_POINTS; i++) {

JOptionPane.showMessageDialog(null, "Point number " + (i + 1) + " is: " + this.coordinateList.get(i));

}

}

/**
* This sorts the points by the X coordinates
*/
public void sortByXCoordinates() {

Collections.sort(this.coordinateList, new PointCompare());

}

public class PointCompare
implements Comparator<Point> {

public int compare(final Point a, final Point b) {
if (a.x < b.x) {
return -1;
}
else if (a.x > b.x) {
return 1;
}
else {
return 0;
}
}
}

public static void main(final String[] args) {
final MainClass main = new MainClass();

main.inputCoordinates();
main.displayPoints();

}
}

Sort an ArrayList of Points in page line order

This should work for you. Sort the Points by Y coordinate first and then by X coordinate.

Point p1 = new Point(12,  15);
Point p2 = new Point(13, 12);
Point p3 = new Point(14, 15);

List<Point> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);

Comparator<Point> comp = new Comparator<Point>() {
@Override
public int compare(Point p1, Point p2) {
return p2.y == p1.y ? p2.x -p1.x : p2.y-p1.y;
}
};
list.sort(comp);

Sorting array in java using a reference point

There are two things going on here: First there's the math. If I understand correctly, you're effectively going to compare Math.abs(a-L1) and Math.abs(b-L1) so we would have a closure like

myArrayList.sort((a,b) -> Double.compare(Math.abs(a-L1), Math.abs(b-L1)));

but since L1 is used inside the lambda, it must be effectively final so we will need to have L1 initialized as final:

final double L1 = 42;

Of course in your case you need to replace Math.abs with an appropriate function that measures the distance from a point a to L1 and initialize L1 appropriately with an instance of your 2D coordinates.

How to sort a collection of points so that they set up one after another?

My thinking is that you first need a mathematical definition of your ordering. I suggest (Note, this definition wasn't clear in the original question, left here for completeness):

Starting with placing any point in the sequence, then perpetually append to the sequence the point closest to the current point and that hasn't already been appended to the sequence, until all points are appended to the sequence.

Thus with this definition of the ordering, you can derive a simple algorithm for this

ArrayList<point> orderedList = new ArrayList<point>();

orderedList.add(myList.remove(0)); //Arbitrary starting point

while (myList.size() > 0) {
//Find the index of the closest point (using another method)
int nearestIndex=findNearestIndex(orderedList.get(orderedList.size()-1), myList);

//Remove from the unorderedList and add to the ordered one
orderedList.add(myList.remove(nearestIndex));
}

The above is pretty universal (regardless of the algorithm for finding the next point). Then the "findNearestIndex" method could be defined as:

//Note this is intentially a simple algorithm, many faster options are out there
int findNearestIndex (point thisPoint, ArrayList listToSearch) {
double nearestDistSquared=Double.POSITIVE_INFINITY;
int nearestIndex;
for (int i=0; i< listToSearch.size(); i++) {
point point2=listToSearch.get(i);
distsq = (thisPoint.x - point2.x)*(thisPoint.x - point2.x)
+ (thisPoint.y - point2.y)*(thisPoint.y - point2.y);
if(distsq < nearestDistSquared) {
nearestDistSquared = distsq;
nearestIndex=i;
}
}
return nearestIndex;
}

Update:
Since the question was revised to largely adopt the definition I used, I took out some of the caveats.

Java sorting list of array vs sorting list of list

I am missing something trivial

Method equals() should be used for object comparison. Double equals == checks whether two references point to the same object in memory.

If you change the condition inside the comparator to !a.get(0).equals(b.get(0)) it will work correctly.

However, (10001, -10) was put before (10001, -8). Even though -8 is larger than -10.

The reason for such behavior is that JVM caches all the instances of Integer (as well as Byte, Short and Long) in the range [-128; 127]. I.e. these instances are reused, the result of autoboxing of let's say int with a value of 12 will be always the same object.

Because small values in your example like 3, 5, 12 will be represented by a single object, they were compared with == without issues. But the result of comparison with == for two Integer instances with a value of 10001 will be false because in this case there will be two distinct objects in the heap.

The approach of caching frequently used objects is called the Flyweight design pattern. It's very rarely used in Java because this pattern can bring benefits when tons of identical objects are being created and destroyed. Only in such a case caching these objects will pay off with a significant performance improvement. As far as I know, it's used in game development.

Use the power of objects

Point must be an object, not a list, as Code-Apprentice has pointed out in his answer. Use the power of objects and don't overuse collections. It brings several advantages:

  • class provides you a structure, it's easier to organize your code when you are thinking in terms of objects;
  • behavior declared inside a class is reusable and easier to test;
  • with classes, you can use the power of polymorphism.

Caution: objects could be also misused, one of the possible indicators of that is when a class doesn't declare any behavior apart from getters and its data is being processed somehow in the code outside this class.

Although the notion of point (as a geometrical object) isn't complicated, there are some useful options with regard to methods. For example, you could make instances of the Point class to be able to check to whether they are aligned horizontally or vertically, or whether two points are within a particular radius. And Point class can implement Comparable interface so that points will be able to compare themselves without a Comparator.

Sorting

With Java 8 method sort()
was added to the List interface. It expects an instance of Comparator, and if element of the list implement comparable, and you want them to be sorted according to the natural order null can be passed as an argument.

If the specified comparator is null then all elements in this list must implement the Comparable interface and the elements' natural ordering should be used.

So instead of using utility class Collections you can invoke method sort() directly on a list of points (assuming that Point implements Comparable<Point>):

points.sort(null); // the same as   points.sort(Comparator.naturalOrder()); 

Also, you can create multiple custom comparators by utilizing default and static methods from the Comparator interface like comparingInt() and thenComparing().

(for more information on how to build comparators with Java 8 methods take a look at this tutorial)

Java/ Sort array which contain points

You can use Arrays.sort with a custom Comparer<Point>:

Arrays.sort(p, new Comparator<Point>() {
int compare(Point a, Point b) {
int xComp = Integer.compare(a.x, b.x);
if(xComp == 0)
return Integer.compare(a.y, b.y);
else
return xComp;
}
});

Sidenotes:

  • If some of your Point objects may be null, you must handle this
    in compareTo.
  • If your Point is not an AWT point but your own
    class, you'd better let it implement Comparable.


Related Topics



Leave a reply



Submit