How can I improve this Point class - java

I'm writing a program that will need to use a limited set of Points to process an image. I figure that I would implement it as an immutable/singleton style class. Before going on to build more of the complex logic surrounding the class I wanted to get an opinion about the core class.
import org.apache.commons.lang3.builder.HashCodeBuilder;
import java.util.HashMap;
public class Point {
private final int x,y;
private final int hashCode;
private static final HashMap<int[],Point> points = new HashMap<>();
private Point(int x,int y){
this.x = x;
this.y = y;
this.hashCode = new HashCodeBuilder().append(x).append(y).toHashCode();
}
public static Point getPoint(int x,int y){
int [] candidate = new int[]{x,y};
if(points.containsKey((candidate))){
return points.get(candidate);
}
Point newPoint = new Point(x,y);
points.put(candidate, newPoint);
return newPoint;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public int hashCode(){
return hashCode;
}
#Override
public boolean equals(Object p){
return this == p;
}
}
I'm going to be using the class to do at least the following functions:
Map different channels in an image by this Point class
Define some static cached custom NavigableSets for ease of traversal
Various Helper functions. In example, get all Points surrounding a Point
Given the information provided, what are some downsides of the provided implementation?
Note: Putting the bulleted list before the code block breaks the display of the code block. Bug?

I think your caching "singletony" stuff may be pointless.
It doesn't save on object creation, as you will always create a candidate[] each time you ask for a Point. And, unless the Point gets reused, you use the memory for candidate and the Map.Entry in your HashMap. So, very roughly speaking, unless each Point gets reused three times, your caching uses more memory. And it always uses a more time.
If you don't cache, change your equals of course.
p.s. the rest seems fine, and immutable is good. You could consider making x and y public final to be more compatible with other Point implementations.

If you are worried about the occupied memory, there is another way to deal with it.
I assuming you have limited dimension for your points, I would suggest to combine your x & y in one variable of long (in case your dimensions is 32 ints long), or even int (if you can fit one dimensions in 16 bit), this way you'll get boost in performance & memory.
Other option is to use int[] array of your coordinates for a point, although that would take more space (since you would have to keep additional pointer reference).
Factory method in your implementation, will work only on single threaded applications, if you have multiple threads creating points, you would need to have some concurrency control in place. This would eat up your resources, because you would effectively need to lock on each point creation.
Another reason, why this Factory method is a bad idea, is that int[] arrays do not override equals and hashCode, you can try to create 2 arrays with same content, to check. So your HashMap would not simply work, and instead of saving memory you would not only create a new Point each time, but also add an entry to your HashMap and perform unnecessary calculations.
So either use Java primitives, or just create a new immutable Point each time if you need too, and go with it, don't overcomplicate with factoryMethods.

You had the right idea of making the Point class immutable but then you went and complicated things with the instance cache. It is not thread safe and it will leak memory because once a Point is created it will forever stay in the hashmap and will never be garbage collected.
Why not keep it simple and make a regular boring value class? Your IDE will even generate it for you.
Then, if you really really really want to have an instance cache, use Guava's Interner class instead of rolling your own. The result will look something like this:
public class Point {
final int x;
final int y;
private Point(int x, int y) {
this.x = x;
this.y = y;
}
static Interner<Point> instanceCache = Interners.newWeakInterner();
public static Point of(int x, int y) {
return instanceCache.intern(new Point(x,y));
}
public int getX() { return x; }
public int getY() { return y; }
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point other = (Point) o;
return this.x == other.x && this.y == other.y;
}
#Override
public int hashCode() { return x * 31 + y; }
}

Related

Does java cache method results?

If i have an immutable class like this:
public class MathClass {
private final int x;
public MathClass(int x) {
this.x = x;
}
public int calculateSomething() {
return Math.sqrt(x);
}
}
Does the jvm cache the result of calculateSomething() on the first call?
I have a more complicated calculation in the MathClass.
No it does not, only the object is stored within the cache
You could use your own caching solution, such as Spring's #Cacheable to store method results in cache
No, Java doesn't cache method results in general.
Some few methods of the Framework do this, but it's part of their implementation, e.g. Integer.valueOf(int).
c.f. JavaDoc:
This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range."
But with your implementation it would be easy to implement the "caching" by yourself: the class is immutable, that means the inputs don't change, so you can easily calculate the value on the first request and return the previously calculated value on subsequent requests:
public class MathClass {
private final int x;
private transient boolean calculated = false;
private transient int preCalcSomething;
public MathClass(int x) {
this.x = x;
}
public int calculateSomething() {
if (!calculated) {
preCalcSomething = Math.sqrt(x);
calculated = true;
}
return preCalcSomething;
}
}
I used the transient keyword here to mark that those two fields are not part of the "object state". Don't forget to exclude them from equals and hashCode calculations and maybe other state-depending methods!
If you are using an object instead of a primitive, I would use null as indicator for "not yet calculated" if that is a value that cannot be the actual result of the cached operation.
You could calculate it just once, and then return the result previously calculated.
public class MathClass {
private final int x;
private final int result;
public MathClass(int x) {
this.x = x;
this.result = Math.sqrt(x);
}
public int calculateSomething() {
return result;
}
}
The calculation will not be performed more than one time. This is not a cache but works as one in your scenario.

Why doesn't Project Valhalla introduce mutable structs?

Looks to me like primitive classes could behave more efficiently (at reasonable sizes) if they weren't immutable as currently proposed, but worked more like C structs.
Given this primitive class
primitive class Point implements Shape {
public long x;
public long y;
public Point(long x, long y) {
this.x = x;
this.y = y;
}
public boolean contains(Point p) {
return equals(p);
}
}
interface Shape {
boolean contains(Point p);
}
And an array Point[] points = new Point[N];
Why wouldn't we be able to do this?
points[0].x = 42; //lastore
points[1].x++; //laload, iinc, lastore
Point p = points[2]; //laload, laload
Shape s = p; //new Point.ref (boxing)
p.x++; //iinc
assert !s.contains(p);
Instead it sounds like current design intends for the whole Point be read, mutated using withfield and written back in its entirety, which seems kind of wasteful - especially for larger types. Or would compilers routinely apply copy elision here?
Note that Point must be flattened instead of flattenable here, so the user can be certain not to mutate a shared instance.
Could someone further clarify the rationale behind immutability of primitive types?
#see
JEP 401: Primitive Classes (Preview)
State of Valhalla - Part 3: The JVM Model

"this" objects vs non-static objects

Consider this:
public class Test {
public static int numberOfInstances = 0;
public int myInstanceID;
public String myInstanceName;
The static variable doesn't need to be called within an instance, it's available everywhere like this:
Test.numberOfInstances
When creating an instance, I only do this into my constructor:
public Test(int id, String name) {
myInstanceID = id;
myInstanceName = name;
numberOfInstances += 1;
}
I've recently discovered the this keyword and have noted some of its uses:
public Test() {
this(numberOfInstances + 1, "newInstance");
numberOfInstances += 1;
}
From what I've noticed, the this keyword allows you to call another one of the class' constructors. It also allows you to do this:
public Test(int x, int y) {
this.x = x;
this.y = y;
}
With java, I highly disagree with this style; same variable names, and I don't see the point of using this, especially after looking at the docs example. I look at this:
public Test(int a, int b) {
x = a;
y = b;
However, the use of the this keyword isn't necessary; In my code, I have a variables in my class (e.g. xCoordinate) where I don't use the this keyword (it's not static).
What I've been struggling to understand is what the difference is between non-static variables and this variables. Is there a difference? In one of my classes (the Paddle for Pong), I have this:
public class Pong {
public int xCoordinate;
public int yCoordinate;
and so on...
I never use the this keyword anywhere, and the data is stored within it's own instance.
Bottom line, my question is what is the difference between non-static variables and this.variables. Is it a standard coding practice? Why would I ever you the this keyword on non-static variables?
I think you may have almost answered your own question. You provided the function
public Test(int x, int y) {
this.x = x;
this.y = y;
}
However, what do you think would happen if you wrote it this way instead?
public Test(int x, int y) {
x = x;
y = y;
}
Noticed that I removed the this in the second function. Therefore, x and y would just be referring to the local x and y variables. this allows you to specify that you actually want to use the non-static class variables x and y.
If, as is typical, the parameter variable names of a constructor (say x) are the same as fields of the class, then the field names are shadowed by the parameters passed.
this is used in this case to disambiguate: this.x denotes the field x. It makes perfect sense. this means "reference to the current instance".
So, statements like this.x = x; are quite common.
If you still continue to dislike the Java style, and you adopt m_x-style notation for class fields, then you can write m_x = x; in your constructor. As you rightly point out, this is then not required.
this is also used as the notation for delegating constructors, as you point out.
The "this" keyword allows you to difference between method and instance variables:
public class Point {
private int x;
private int y;
public void add(int x, int y) {
this.x += x;
this.y += y;
}
}
There is no this variables. It's just used to tell the compiler that the variable you want to change is the declared field and not the local variable, in case they have the same name.
For the constructor part, this is just a shortcut for classes which have multiple constructors. You can write the code once and just call that from the alternative constructors.
There is also a similiarly used keyword super, which allows you to call methods and constructors of the superclass:
public SomeClass(int x) {
super(x);
super.someMethod(); // even if we would have overridden someMethod(),
// this will call the one from the superclass
}
Here's one instance where you would need the 'this' keyword:
public class Pong {
public int xCoordinate;
public int yCoordinate;
public Pong (int xCoordinate, int yCoordinate) {
this.xCoordinate = xCoordinate;
this.yCoordinate = yCoordinate;
}
}

Call a method from another class(not main class)

How to call distanceTo(Point p) of Point.java into Point2.java under a method takes no parameter? There should be a way but I cannot find from my materials. Could anybody help me? It has been doing 2 days. Please help...
---------------------Point.java---------------------------------
public class Point{
private int x;
private int y;
//x and y coordinates as parameters
public Point(int x, int y){
this.x = x;
this.y = y;
}
//I want to call this method by calling a method which taken no parameter in Point2.java.
public double distanceTo(Point p){
return Math.sqrt(((x - p.x) * (x - p.x)) + ((y - p.y) * (y - p.y)));
}
}
---------------------ClonePoint.java---------------------------------
public class ClonePoint{
private int a;
private int b;
//x and y coordinates as parameters
public ClonePoint(int a, int b){
this.a = a;
this.b = b;
}
//I failed with this way. Can anybody correct me?
public double measureDistance(){//it should be takes no parameter.
return distanceTo(ClonePoint p)
}
}
----------------------PointDriver.java-----------------------------
public class PointDriver {
public static void main(String [] args) {
Point2 nn = new Point2(11, 22);
Point2 mm = new Point2(33, 44);
System.out.println(nn.distanceTo(mm)); //I succeeded with this!
System.out.println(nn.measureDistance(mm)); //But I got an error illegal start of expression
}
}
#Evan a class is a generalized container for your things. A car, a person, a point (in your case).
Everytime you want to "create" one or more object of your defined class, you instantiate them:
Person evan = new Person();
Person rob = new Person();
both of us are person, you don't really need to define class Person1 and Person2!
And in a class you should define the methods used to "relate" to other similar objects.
For example:
// In Person.java
public void greet(Person p) {
System.out.println("My name is "+this.name+". Nice to meet you +"p.getName());
}
// In main
rob.greet(evan); // it now gives compile errors of course but take the point :P
What you want to achieve is to create a better and more complete Point class with all the methods you want to use. In the end, just initialize more Point objects (same class!) in your main and play with them.
Hope it helps :)
EDIT
Ok, perhaps I've got what your homework wants you to perform.
A "parameter-less" method measureDistance() should make you wonder one important thing: "distance FROM which point????".
Obviously, if the function takes no parameters all the information needed to that calculus must be in the object which calls it. Don't you think?
So, you probably want to achieve a secondary class (if you really need to define it as Point2 it's ok, but change that name because it's confusing) which can take a Point in its constructor (saving this information in itself) and then use that Point to measure distance from it.
Example
public class Point2{
private int a;
private int b;
private Point startingPoint;
public Point2(int a, int b, Point p){
this.a = a;
this.b = b;
startingPoint = p;
}
// Computes the distance from starting point to this
public double measureDistance(){//it takes no parameter.
return startingPoint.distanceTo(a, b);
}
/*
if you can't edit distanceTo() it gets a little verbose but you must create a
Point with Point2 coordinates - remember this example when you will study Inheritance
public double measureDistance() {
Point endingPoint = new Point(a, b);
return startingPoint.distanceTo(endingPoint);
}
*/
}
First, it is not good idea to duplicate a class that does the same thing because you are doing extra unneeded work. Second, if you make various point types, you are loosing the advantage of seamless compatibility between them.
Then, if you want to call method from other class you can do it like this:
NameOfOtherClass.SomeMethod()
But you have to declare the SomeMethod in the other class as static...
public static double SomeMethod() { ... };
But then you can't use the method to access the data of your concrete points you have created in your code, so any data should be put into parameters.
If you want to do it your way, you have to just add a parameter to public double measureDistance()
function so the function has access to another point to measure distance to.

Java newbie: How to assign current state of object to another, without establishing reference?

Once again, I'm looking for a way to bypass this array problem, how? Is there any way other than clone()?
I'm asking because fighting with clone(), protection and implemention stuff didn't work for me...
//assuming you have proper class and constructor (point(int x, int y))
/*
point 7POINTSARRAY[]=new point[7];
for(int i=0;i<7;i++)
{
7POINTSARRAY[i].x=i;
7POINTSARRAY[i].y=i;
}
//This won't work, so...
*/
point B = new point(0,0); // You need this.
for(int i=0;i<7;i++){
7POINTSARRAY[i]=B; // And this.
//But I want to read and assign value only,
// not establish a reference, so it can work How?
7POINTSARRAY[i].x=i;
7POINTSARRAY[i].y=i;
System.out.println(7POINTSARRAY[i].x);
}
System.out.println(7POINTSARRAY[1].x);
Though desired output is A[1].x=1, it's been owerwritten several times, and now A[1].x = 7.
You need to a create a new point for every element of the array if you want them all to reference different objects:
for(int i=0;i<7;i++)
{
point B = new point(0,0); // Put this *inside* the loop
7POINTSARRAY[i]=B; // Now B is a new instance of point
7POINTSARRAY[i].x=i;
7POINTSARRAY[i].y=i;
System.out.println(7POINTSARRAY[i].x);
}
System.out.println(7POINTSARRAY[1].x); // should now print 1
I haven't changed your code formatting but improving that will make the above clearer and easier to understand.
Sorry but Java works only with references for complex objects. You should use and implement clone() correctly this can't be the problem. clone() is well defined approach.
Typical clone for first level class looks like following
#Override
public Object clone() {
try {
A ans = (A) super.clone();
// do complex stuff
return ans;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
the line
A ans = (A) super.clone();
does default clone, which includes cloning object but not it's members. You should cascade clone for members. Since clone() is a member, it has access to protected members of the parent.
If your parent is Cloneable you should write
#Override
public Object clone() {
A ans = (A) super.clone();
// do complex stuff
return ans;
}
because parent can't throw exception.
For example, if you have point class looking like follows
class point {
public point(double x, double y) { this.x = x; this.y = y; }
public double x;
public double y;
}
then you should just fix it in the following way
class point implements Cloneable {
public point(double x, double y) { this.x = x; this.y = y; }
public double x;
public double y;
}
to make it cloneable.
Then you will be able to write
point a = new point(1,2);
point b = (point) a.clone();
and you will get 2 separate copies.
the problem is with the line
7POINTSARRAY[i]=B
which means that each object in 7POINTSARRAY refer (or points) to the same object B.
so when you do inside the loop
7POINTSARRAY[i].x=i;
7POINTSARRAY[i].y=i;
you actually always changing B.
You should do instead:
for(int i=0;i<7;i++){
7POINTSARRAY[i] = new point(i,i);
}

Categories