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 benull
, you must handle this
incompareTo
. - If your
Point
is not an AWT point but your own
class, you'd better let it implementComparable
.
Related Topics
Why Shouldn't I Call Setvisible(True) Before Adding Components
Convert Java.Time.Localdate into Java.Util.Date Type
Is a Java Array of Primitives Stored in Stack or Heap
Is Jdk "Upward" or "Backward" Compatible
Package Conflicts with Automatic Modules in Java 9
What Is Difference Between Crudrepository and JPArepository Interfaces in Spring Data JPA
Configuring Spring Security 3.X to Have Multiple Entry Points
Static Fields on a Null Reference in Java
How to Use Aop with Aspectj for Logging
Can "This" Ever Be Null in Java
Highlighting Strings in Javafx Textarea
Differencebetween I++ & ++I in a for Loop
How to Redirect to Login Page When Session Is Expired in Java Web Application
How to Call the Overridden Method of a Superclass
Is Java.Util.Date Using Timezone
How to Get the Latest Jre/Jdk as a Zip File Rather Than Exe or Msi Installer