Java make custom object comparable? - java

I have the object below.
public class Coords {
public int x;
public int z;
public Coords(int x, int z) {
this.x = x;
this.z = z;
}
}
How can this implement Compareable?
Im not sure what the compareTo method should be doing.
#Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}

You could compare x and then compare z (alternatively, z and then x). Also, I suggest you override toString. Something like,
public class Coords implements Comparable<Coords> {
public int x;
public int z;
public Coords(int x, int z) {
this.x = x;
this.z = z;
}
#Override
public int compareTo(Coords o) {
if (this.x == o.x) {
if (this.z == o.z) {
return 0;
}
return this.z < o.z ? -1 : 1;
}
return this.x < o.x ? -1 : 1;
}
#Override
public String toString() {
return String.format("{%d, %d}", x, z);
}
}

Here are the details of compareTo:
Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
I'd suggest something like this:
#Override
public int compareTo(Coords other) {
return this.x == other.x ? (this.z == other.z ? 0 : this.z - other.z) : this.x - other.x
You can make z more significant if you switch them.

Related

How to make two objects equal in contains method of Hashset [duplicate]

This question already has answers here:
What issues should be considered when overriding equals and hashCode in Java?
(11 answers)
Closed last year.
I have created a Pair Class which has 3 variables mentioned below and overrides the equals method as well assuming this is used in contains method of hashset. But it is not. Can someone explain what to implement in Pair class to make sure it equats the values of x and y only.
Class Pair extends Object {
int x;
int y;
int dis;
public Pair(int x, int y, int d) {
this.x = x;
this.y = y;
this.dis = d;
}
#override
public boolean equals(Pair p) {
return this.x == p.x && this.y == p.y
}
}
Whenever you overide equals, you should also override hashCode:
#Override
public int hashCode() {
return Objects.hash(x,y);
}
See the general contract of equals and hashCode:
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html
It is generally necessary to override the hashCode method whenever equals method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
import java.util.HashSet;
class Point extends Object {
int x, y, dis;
Point(int x, int y) {
this.x = x;
this.y = y;
this.dis = (int) Math.sqrt(x * x + y * y);
}
#Override
public boolean equals(Object o) {
if (o instanceof Point) {
Point p = (Point) o;
return p.x == x && p.y == y;
}
return false;
}
#Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public class Equals {
public static void main(String[] args) {
HashSet<Point> set = new HashSet<Point>();
set.add(new Point(1, 2));
set.add(new Point(1, 2));
set.add(new Point(1, 3));
System.out.println(set.size());
}
}
See equals API doc.

How can I write a Comparator comparing multiple arguments? [duplicate]

This question already has answers here:
How to compare objects by multiple fields
(23 answers)
Closed 4 years ago.
Im trying to write a Comparator which compares two objects of the class Coordinate. The Coordinate class is Pretty simple:
public class Coordinate {
private int x, y;
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
Now I want the Comparator to compare the x and the y value for two instances of the class Coordinate. Here is an example:
I have a Coordinate c1 which has x = 42 and y = 23. My second Coordinate c2 has x = 23 and y = 54. Now i put them both in an ArrayList an want to sort the List. I wanted to be sorted like the following:
The Coordinate with the lowest y value goes Always first, when you have two Coordinates having the same y value the Coordinate goes first which has a lower x value.
Example:
c1 (y = 4, x = 5 ) < c2 (y = 4, x = 6) < c3 (y = 5, x = 2)
So how can I write a Comparator for this Purpose?
Thank you very much!
Comparator<Coordinate> c = Comparator.comparingInt(Coordinate::getY)
.thenComparingInt(Coordinate::getX);
You can build compound comparators by means of thenComparing and thenComparingX.
var list = List.of(
new Coordinate(6, 4),
new Coordinate(2, 5),
new Coordinate(5, 4)
);
list.sort(c);
System.out.println(list);
The snippet prints
[{y=4, x=5}, {y=4, x=6}, {y=5, x=2}]
Using Comparator
import java.util.ArrayList;
import java.util.Comparator;
class Coordinate {
private int x, y;
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String toString() {
return "x = " + x + " y = " + y;
}
}
public class Temp {
public static void main(String[] args) {
ArrayList<Coordinate> A = new ArrayList<>();
A.add(new Coordinate(1, 2));
A.add(new Coordinate(2, 1));
A.add(new Coordinate(3, 2));
A.sort(new Comparator<Coordinate>() {
#Override
public int compare(Coordinate o1, Coordinate o2) {
if (o1.getY() < o2.getY()) {
return -1;
} else if (o1.getY() > o2.getY()) {
return 1;
} else {
if (o1.getX() < o2.getX()) {
return -1;
} else if (o1.getX() > o2.getX()) {
return 1;
}
return 0;
}
}
});
System.out.println(A.toString());
}
}
Using Comparable Interface
import java.util.ArrayList;
class Coordinate implements Comparable<Coordinate> { # Notice implementing Comparable interface
private int x, y;
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
#Override
public int compareTo(Coordinate o) { # implementing the abstract method of Comparable interface
if (y < o.y) {
return -1;
} else if (y > o.y) {
return 1;
} else {
if (x < o.x) {
return -1;
} else if (x > o.x) {
return 1;
}
return 0;
}
}
public String toString() {
return "x = " + x + " y = " + y;
}
}
public class Temp {
public static void main(String[] args) {
ArrayList<Coordinate> A = new ArrayList<>();
A.add(new Coordinate(1, 2));
A.add(new Coordinate(2, 1));
A.add(new Coordinate(3, 2));
A.sort(null);
System.out.println(A.toString());
}
}
Output
[x = 2 y = 1, x = 1 y = 2, x = 3 y = 2]

Java Algorithm for finding shortest distance between 2d point and Matrix

I'm stuck on this question for a couple of days now and would really like to get some help.
I am given a 2 dimensional point in the range of (0-1 not including 1), such as (0.5,0.2), and N other points (also in the range of 0-1).
The first part of the question is to implement the "dumb" algorithm, which when given a certain point will find the point with the shortest distance from it, which has a complexity of O(N).
The part I'm stuck at, requires to build a Matrix K on K, where each "cell" will contain the points that belong to that cell. Once done, when given the original point I will need to search for the point with the shortest distance to it only in some of the cells and not the entire Matrix, which should result better complexity.
My original thought is to devide the points so that each block will have an arraylist of points that belong to him, and then to somehow go through the main block(the one that the original point belongs to) and continue by going through it's neighbors, however implementing it hasn't been very successful.
I would highly appreciate any help/ advice.
Below is what I currently have:
public class Point {
private double x;
private double y;
private Block b;
public Point(double x, double y)
{
this.x=x;
this.y=y;
}
public Point(double x, double y, Block b) //consrtuctor for complex case
{
this.x=x;
this.y=y;
b.points.add(this);
}
public double getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public double distance(Point p)
{
double res=0;
res = Math.sqrt(Math.pow(this.x-p.getX(),2)+Math.pow(this.y-p.getY(),2));
return res;
}
}
import java.util.ArrayList;
public class Block {
private int x;
private int y;
public ArrayList<Point> points;
public Block(int x, int y) {
points = new ArrayList<Point>();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
import java.util.Random;
public class ComplexCase {
private Block[][] blockMat;
public ComplexCase(int k, int n)
{
Random generator = new Random();
Point p1;
Block b1;
double x,y;
int bx1,by1;
int t;
t = 1/k;
blockMat = new Block[k][k];
for (int i =0;i<n;i++)
{
x = generator.nextDouble();
y = generator.nextDouble();
bx1 = (int) (x/t);
by1 = (int) (y/t);
b1 = new Block(bx1,by1);
p1 = new Point(x,y,b1);
}
}
public Block[][] getBlockMat() {
return blockMat;
}
public void setBlockMat(Block[][] blockMat) {
this.blockMat = blockMat;
}
}

Overriding hashCode() not working

I'm trying to make class Point work correctly with a HashSet. Here is my Point class:
class Point {
int x;
int y;
Point(int x, int y) {
x = x;
y = y;
}
#Override
public int hashCode() {
int hash = 1;
hash = hash * 17 + x;
hash = hash * 31 + y;
return hash;
}
#Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
Point p = (Point) o;
return x == p.x && y == p.y;
}
}
When I test it out and do
HashSet<Point> h = new HashSet<Point>();
h.add(new Point(0, 0));
Point g = new Point(0, 1);
System.out.println(h.equals(g));
System.out.println(h.contains(g));
The output is this
false
true
Why is my hashCode not working?
In
Point(int x, int y) {
x = x;
y = y;
}
You are assigning x, the local parameter variable, to itself. Same for y. These are no-ops.
Use
Point(int x, int y) {
this.x = x;
this.y = y;
}
so that you assign the parameter value to the field.
As others have noted, you shouldn't do
Point p = (Point) o;
without knowing if o is a Point or not. It will throw a ClassCastException if it is not assignable to a Point. Instead use
if (o instanceof Point)
return false;
or
if (o.getClass() != Point.class)
return false;
before casting. Note that the two methods above are not equivalent. You can use the first in most cases, but use the second if Point is meant to have sub classes.

How to make my HashMap work as expected?

Suppose one has a simple class:
public class Point implements Comparable<Point> {
public int compareTo(Point p) {
if ((p.x == this.x) && (p.y == this.y)) {
return 0;
} else if (((p.x == this.x) && (p.y > this.y)) || p.x > this.x) {
return 1;
} else {
return -1;
}
}
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
And a HashMap from Point to something, let's say Cell:
cellMap = new HashMap<Point, Cell>();
Then one fills in cellMap as follows:
for (int x = -width; x <= width; x++) {
for (int y = -height; y <= height; y++) {
final Point pt = new Point(x,y);
cellMap.put(pt, new Cell());
}
}
}
And then one does something like (trivial) this:
for (Point pt : cellMap.keySet()) {
System.out.println(cellMap.containsKey(pt));
Point p = new Point(pt.getX(), pt.getY());
System.out.println(cellMap.containsKey(p));
}
And gets true and false in, respectively, first and second cases. What is going on? Is this map comparing hashes instead of values? How to make the example return true in both cases?
Since you are using HashMap, not TreeMap, you need to override hashCode and equals, not compareTo, in your Point class:
#Override
public int hashCode() {
return 31*x + y;
}
#Override
public bool equals(Object other) {
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof Point)) return false;
Point p = (Point)other;
return x == p.x && y == p.y;
}

Categories