Java - Implement Cloneable or add a constructor? - java

Hey I'm actually working with a custom Vector class on Java,
public class Vector {
private double X;
private double Y;
public Vector(double x, double y) {
this.X = x;
this.Y = y;
}
public void setX(double x) {
this.X = x;
}
public double getX(double x) {
return this.X;
}
public void setY(double y) {
this.Y = y;
}
public double getY(double y) {
return this.Y;
}
}
I wanted to add the multiply() method that would return this vector * by the specified factor like that,
public void multiply(double factor) {
this.X *= factor;
this.Y *= factor;
}
The thing is, when I use a function requiring a vector, I'd like to use it like
doSomething(ancientVector.multiply(-1D));
but the jvm isn't satisfied because the arg I send to the function is a void...
How could I also do to make it clean, should I implement Cloneable or create another constructor working the way multiply does?
doSomething(ancientVector.multiply(-1D));
OR add
public Vector(Vector previous, double mFactor) {
this.X *= previous.getX() * mFactor;
this.Y *= previous.getY() * mFactor;
}

I would keep the class immutable and return a new Vector:
public Vector multiply(double factor) {
return new Vector(X * factor, Y * factor);
}

You could do as #Basti said or you could also return a new instance of your Vector:
public Vector multiply(double factor) {
return new Vector (this.X * factor, this.Y * factor);
}
This way when any change is made to the result of your multiply function it does not affect the initial vector object.

Your Vector will have various operations (you've started with multiply) and its usage looks similar to Java API classes such as BigDecimal. I would therefore recommend following its lead, and make the class immutable. That means all its fields should be final:
public class Vector {
private final double x, y; // Note: final. And use lowercase.
public Vector(double x, double y) {
this.x = x;
this.y = y;
}
// Note: no setters!
public double getX() { // Note: no argument.
return x;
}
public double getY() {
return y;
}
public Vector multiply(double factor) {
return new Vector(x*factor, y*factor);
}
}
One of the advantages of immutable classes is that they are purely value-based so you don't have to worry about copy constuctors or cloning. (By the way, Cloneable is hardly ever used nowadays – copy constructors are preferred – except perhaps for arrays.) Instead of copying, just use assignment: Vector secondVector = firstVector;.

Related

why did this constructor chaining cause stack overflow(java)

So I have the code below but it caused java.lang.StackOverFlowError.
I guess maybe creating an new object inside the second constructor may
have caused an infinite loop or something. But I don't fully understand
why this happened. Could someone explain it to me? I'd appreciate it!
private double x;
private double y;
private double z;
private double[] elements;
/**
* Creates a 3D vector from an array
* #param v array containing 3 components of the desired vector
*/
public Vector3(double[] v) {
this(v[0], v[1], v[2]);
}
/**
* Creates a 3D vector from 3 numeric scalar components
* #param x x coordinate
* #param y y coordinate
* #param z z coordinate
*/
public Vector3(double x, double y, double z) {
this(new Vector3(x, y, z));
}
/**
* Clones an existing vector
* #param old an existing Vector3 object
*/
public Vector3(Vector3 old) {
x = old.x;
y = old.y;
z = old.z;
elements = new double[3];
elements[0] = x;
elements[1] = y;
elements[2] = z;
}
public Vector3(double x, double y, double z) {
this(new Vector3(x, y, z));
}
I'm not sure what you're up to do, but it seems you're calling the Vector3 constructor in itself. This is causing the infinite loop.
In the constructor
public Vector3(double x, double y, double z) {
this(new Vector3(x, y, z));
}
you are calling the same constructor again and again (i.e. new Vector3(x, y, z)). That causes the SOE. This happens before the copy constructor with the call to this(...) even has a chance.
Assuming the following class
public class Vector3 {
// No need for an array. Or if you want an array, discard the doubles.
double x;
double y;
double z;
public double getX() { return x; }
public double getY() { return y; }
public double getZ() { return z; }
}
the correct way to build up constructors is the following:
1) Start with a constructor that builds up a whole instance with all elementary data:
public Vector3(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
2) If you want to add some other convenience constructors, do it his way:
public Vector3(double[] elements) {
this(elements[0], elements[1], elements[2]);
}
3) A copy constructor can be handled the same way:
public Vector3(Vector3 origin) {
this(origin.getX(), origin.getY(), origin.getZ());
}
All the other constructors can be built by calling the first constructor!

How to properly use double coordinates as a key in a HashMap?

I have a class defining a node (a point with three double coordinates).
public class Node {
private final double x, y, z;
public Node() {
}
public Node(final double x, final double y, final double z) {
this.x = x;
this.y = y;
this.z = z;
}
public void setCoordinates(final double x, final double y, final double z) {
this.x = x;
this.y = y;
this.z = z;
}
}
I need to create a lot of nodes and give them integer IDs, but I must avoid duplicates.
The method to create a node looks like this:
private Node vertex = new Node(0, 0, 0);
private final AtomicInteger nodeCounter = new AtomicInteger();
private final Map<Node, Integer> nodeList = new HashMap<>();
public int addNode(final double x, final double y, final double z) {
vertex.setCoordinates(x, y, z);
int nodeId;
if(nodeList.get(vertex) == null) {
nodeId = nodeCounter.incrementAndGet();
nodeList.put(new Node(x, y, z), nodeId);
} else {
nodeId = nodeList.get(vertex);
}
return nodeId;
}
Of course, this does not work because the getfunction of the HashMap always returns null.
So I guess I need to override the hashCode method in the Node class.
I have seen here how to do it for a single double, but I don't know how to create a hash function that would take into account the three coordinates of the node.
Do I also have to override the equals function? Or is the hashCode function enough?
So I guess I need to override the hashCode method in the Node class.
That's only part of the deal. You also need to override equals in order to make your class work as a key of hash map:
#Override
public int hashCode() {
return 31*31*Double.valueOf(x).hashCode()
+ 31*Double.valueOf(y).hashCode()
+ Double.valueOf(z).hashCode();
}
#Override
public boolean equals(Object other) {
if (!(other instanceof Node)) {
return false;
}
Node n = (Node)other;
return x == n.x && y == n.y && z == n.z;
}
In Java 8+, Double.valueOf(x).hashCode() should be replaced with Double.hashCode(x) to avoid unnecessary boxing:
#Override
public int hashCode() {
return 31*31*Double.hashCode(x)
+ 31*Double.hashCode(y)
+ Double.hashCode(z);
}
Do I also have to override the equals function? Or is the hashCode function enough?
Yes, you must always override equals along with hashCode (why?)

Calculate distance between two points in java

I'm kind of new to Java, and trying to write a code that calculate the distance of two points 2 and 3, and scale of 10. Somehow, it does not work. Can you give me a hint, so I can fix the code?
import java.lang.Math;
public class Point {
int x, y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
public float scale(int factor) {
new Point(x * factor, y * factor);
return factor;
}
public float distance(){
double distance = Math.sqrt(x * x + y * y);
return distance;
}
public void main(String[] args) {
float p = new Point(2,3).scale(10);
System.out.println(distance);
}
}
In scale you are creating a new point with the scaled values and doing nothing with it. You're leaving x and y of the point in question untouched.
You probably mean to multiply x and y by factor, rather than creating a new point.
Also you're printing a variable named distance, which does not exist (so this probably doesnt even compile), rather than calling the method named distance() and printing its returned value.
public class Point {
int x, y;
public Point (int x, int y){
this.x = x;
this.y = y;
}
public static Point scalePoint(Point p, int factor) { //scale a given point p by a given factor
Point scaledPoint = new Point(p.x * factor, p.y * factor); //by multipling the x and y value with the factor
return scaledPoint; //and return the new scaled point
}
public static double calculateDistance(Point p1, Point p2){ //to calculate the distance between two points
double distance = Math.sqrt(p1.x * p2.x + p1.y * p2.y); //send the two points as parameter to this method
return distance; //and return the distance between this two as a double value
}
public static void main(String[] args) {
Point p = new Point(2,3);
Point scaledPoint = scalePoint(p, 10);
double distance = calculateDistance(p, scaledPoint);
System.out.println(distance);
}
}
At the moment your distance method is calculating the distance of a point from the origin (i.e. point 0,0). It would make more sense if you made that explicit:
class Point {
private static final Point ORIGIN = new Point(0, 0);
private final int x;
private final int y;
public float distanceTo(Point other) {
float xDelta = other.x - this.x;
float yDelta = other.y - this.y;
return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
}
public Point scale(float factor) {
return new Point(x * factor, y * factor);
}
}
Then finding the distance to the origin becomes point.distanceTo(Point.ORIGIN) which makes the intent clearer.

Why does my class's test program return 0.0 for my answers?

package Geometry;
public class TestGeometryPoint {
public static void main(String[] args) {
//Creates the object PointA and Assigns values
Point pA = new Point(); //PointA(0, 0)
pA.setX(2.0); //PointA(2.0, 0)
pA.setY(5.0); //PointA(2.0, 5.0)
//Creates the object PointB and Assigns values
Point pB = new Point(4.0, 6.1); //PointB(4.0, 6.1)
//Calculates the distance between PointA and PointB
double d = pA.distance(4.0, 6.1); //Distance from class to a set of coordinates
double dP = pA.distance(pB); //Distance from class to another point
double dPtP = Point.distance(pA, pB); //Distance from point to point
//Prints the result of the calculations
System.out.println("Distance between Point A & B: " + d);
System.out.println("Distance between Point A & B: " + dP);
System.out.println("Distance between Point A & B: " + dPtP);
}
}
This is my Test Class and my Point class below.
package Geometry;
public class Point {
//Initializes the coordinates for a point on a graph with the values of x and y
private static double x;
private static double y;
//Defualt Constructor
public Point() {
x = 0;
y = 0;
}
//Point Constructor
public Point(double x, double y) {
this.x = x;
this.y = y;
}
//Returns the x value
public double getX() {
return x;
}
//Changes the x value
public void setX(double x) {
Point.x = x;
}
//Returns the y value
public double getY() {
return y;
}
//Changes the y value
public void setY(double y) {
Point.y = y;
}
//Calculates the distance between the class's point coordinates and another set of point coordinates
public double distance(double x0, double y0) {
double distance = (Math.sqrt(((x0 - x) * 2.0) + ((y0 - y) * 2.0)));
return distance;
}
//Calculates the distance between the class's point and another Point class's location
public double distance(Point p) {
double distance = (Math.sqrt(((p.getX() - x) * (p.getX() - x)) + ((p.getY() - y) * (p.getY() - y))));
return distance;
}
//Calculates the distance between a Point class's location and another Point class's location
public static double distance(Point p1, Point p2) {
double distance = (Math.sqrt((Math.pow((p2.getX() - p1.getX()), 2.0) + (Math.pow((p2.getY() - p1.getY()), 2.0)))));
return distance;
}
}
d, dP, dPtP: all return 0.0 when compiled and run, but I have no idea why as I have tried changing code and checking my math when calculating distance. I think I might just need a new set of eyes to take a look at it.
I believe since your x and y variables are static, they belong to the class Point as a whole. When you create a Point(2,5);
You set the static variable of the class Point to be 2 and 5 and then, you create another Point(4,6) You set the same static value of x and y to be 4,6.
Therefore, comparing the distance between the same two Point are 0.
The right code for the class Point would be like so
public class Point {
//Initializes the coordinates for a point on a graph with the values of x and y
private double x;
private double y;
//Defualt Constructor
public Point() {
x = 0;
y = 0;
}
//Point Constructor
public Point(double x, double y) {
this.x = x;
this.y = y;
}
//Returns the x value
public double getX() {
return x;
}
//Changes the x value
public void setX(double x) {
this.x = x;
}
//Returns the y value
public double getY() {
return y;
}
//Changes the y value
public void setY(double y) {
this.y = y;
}
//Calculates the distance between the class's point coordinates and another set of point coordinates
public double distance(double x0, double y0) {
double distance = (Math.sqrt(((x0 - x) * 2.0) + ((y0 - y) * 2.0)));
return distance;
}
//Calculates the distance between the class's point and another Point class's location
public double distance(Point p) {
double distance = (Math.sqrt(((p.getX() - x) * (p.getX() - x)) + ((p.getY() - y) * (p.getY() - y))));
return distance;
}
//Calculates the distance between a Point class's location and another Point class's location
public static double distance(Point p1, Point p2) {
double distance = (Math.sqrt((Math.pow((p2.getX() - p1.getX()), 2.0) + (Math.pow((p2.getY() - p1.getY()), 2.0)))));
return distance;
Your problem is that you are confusing static and non-static fields.
By putting that little static on your field declarations you are saying: all instances of this class should be seeing the exact same variables.
So, when you create two points
p1 = new Point(5, 5);
p2 = new Point(10, 10);
the declaration of p2 "overrides" the 5-5 from p1 ... because, as said: all Points are using the same x and y.
Thus, solution: simply drop that keyword from the definition of x and y. Then each point has is very own x and y.
And, more importantly: understand that each and any character in your source code matters. This means: you better understand each and any concept that your source code is making use of!

How to assign coordinates (x,y) to an Array and calculate distance between them? (Java)

I am new to Java.
How do I assign a list of items with coordinates e.g. (x,y) to an Array and to calculate the distance between each of them?
Grateful if anyone could help!
What have you tried? You'll do better here if you actually post code that you've written and show some effort.
Start with a Point:
public class Point {
private final double x;
private final double y;
public Point(x, y) {
this.x = x;
this.y = y;
}
public static double distance(Point a, Point b) {
double dx = a.x - b.x;
double dy = a.y - b.y;
return Math.sqrt(dx*dx + dy*dy);
}
}

Categories

Resources