implementing own compareTo and compare Methods - java

im working on some old tasks given by my Programming course.
Im supposed to create a Rectangle class with some basic functions and a lot of Comparable and Comparator classes.
This is what I've got already:
public class Rectangle {
private int length, width;
public Rectangle(int length, int width) {
this.length = length;
this.width = width;
}
public int length() {
return length;
}
public int width() {
return width;
}
public int area() {
return length + width;
}
public int perimeter() {
return 2 * length + 2 * width;
}
}
public class RectangleComparable extends Rectangle implements Comparable<RectangleComparable> {
public RectangleComparable(int length, int width) {
super(length, width);
}
#Override
public int compareTo(RectangleComparable r) {
if (this.area() < o.area()) return -1;
else if (this.area > o.area()) return 1;
else return 0;
}
}
public class RectangleComparatorArea implements Comparable<RectangleComparable> {
private int area;
#Override
public int compareTo(RectangleComparable r) {
if (area < r.area()) return -1;
else if (area > r.area()) return 1;
else return 0;
}
}
public class RectangleComparatorPerimeter implements Comparable<RectangleComparable> {
private int perimeter;
#Override
public int compareTo(RectangleComparable r) {
if (perimeter < r.perimeter()) return -1;
else if (perimeter > r.perimeter()) return 1;
else return 0;
}
}
public class ComparableComparator<T> implements java.util.Comparator<T> {
public int compare(T o1, T o2) {
return 0;
}
}
What are methods like .compareTo, .equals etc. called? Like, when I got some
obj1.compareTo(obj2);
how can I refer obj1, when I implement my own compareTo method?
Also the ComparableComparator.compare method should work for Rectangles and also other Generic types but I got no idea how to start this.

this . That's the reference to the object whose compareTo get called.
See how jdk's implementation works: java.util.Comparators$NaturalOrderComparator (this is implementation detail and is hidden, tough)

Related

Inheritance var java

this is the qa:
Define a class called MoreSpeed which extends the following class, and which provides a new method called incSpeed() which adds 1 to the inherited variable length.
this is my answer:
public class Speed {
private int length = 0;
public int getSpeed () { return length; }
public void setSpeed (int i) {
if (i > 0) {
length = i;
}
}
}
public class MoreSpeed extends Speed {
private int length;
public int incSpeed() {
return length+1;
}}
its says that the syntax is good but the class operation is wrong.
please help me,thanks.
No. You are shadowing the length from Speed. Instead, implement incSpeed with getSpeed() like
public int incSpeed() {
return getSpeed() + 1;
}
If you are supposed to modify it as well then use setSpeed(int) to do so
public int incSpeed() {
int s = getSpeed() + 1;
setSpeed(s);
return s;
}

Interface and type casting

In the Java 8 tutorial about interface, one example says that when a class implements an interface, one has to type cast the interface type into the class type in order to invoke methods of this class, as shown by the following example from the java 8 tutorial:
public class RectanglePlus
implements Relatable {
public int width = 0;
public int height = 0;
public Point origin;
// four constructors
public RectanglePlus() {
origin = new Point(0, 0);
}
public RectanglePlus(Point p) {
origin = p;
}
public RectanglePlus(int w, int h) {
origin = new Point(0, 0);
width = w;
height = h;
}
public RectanglePlus(Point p, int w, int h) {
origin = p;
width = w;
height = h;
}
// a method for moving the rectangle
public void move(int x, int y) {
origin.x = x;
origin.y = y;
}
// a method for computing
// the area of the rectangle
public int getArea() {
return width * height;
}
// a method required to implement
// the Relatable interface
public int isLargerThan(Relatable other) {
RectanglePlus otherRect
= (RectanglePlus)other;
if (this.getArea() < otherRect.getArea())
return -1;
else if (this.getArea() > otherRect.getArea())
return 1;
else
return 0;
}
}
In the method isLargerThan(Relatable other), other is casted to type RectanglePlus in order to invoke getArea().
In the other example about default methods in interface, the compareTo(Card o) method doesn't type cast o to type PlayingCard, but can invoke int hashCode() directly, I don't understand this. Thanks for your help.
package defaultmethods;
public class PlayingCard implements Card {
private Card.Rank rank;
private Card.Suit suit;
public PlayingCard(Card.Rank rank, Card.Suit suit) {
this.rank = rank;
this.suit = suit;
}
public Card.Suit getSuit() {
return suit;
}
public Card.Rank getRank() {
return rank;
}
public boolean equals(Object obj) {
if (obj instanceof Card) {
if (((Card)obj).getRank() == this.rank &&
((Card)obj).getSuit() == this.suit) {
return true;
} else {
return false;
}
} else {
return false;
}
}
public int hashCode() {
return ((suit.value()-1)*13)+rank.value();
}
public int compareTo(Card o) {
return this.hashCode() - o.hashCode();
}
public String toString() {
return this.rank.text() + " of " + this.suit.text();
}
public static void main(String... args) {
new PlayingCard(Rank.ACE, Suit.DIAMONDS);
new PlayingCard(Rank.KING, Suit.SPADES);
}
}
In short: Because hashCode is defined in java.lang.Object and every other class extends Object implicitly.
So when you have
public int compareTo(Card o) {
return this.hashCode() - o.hashCode();
}
the compiler already knows that o is of type Card which extends Object which defines a hashCode method. No need for an explicit cast.
On the other hand in your isLargerThan method the parameter is of type Relatable:
public int isLargerThan(Relatable other) {
RectanglePlus otherRect
= (RectanglePlus)other;
if (this.getArea() < otherRect.getArea())
return -1;
else if (this.getArea() > otherRect.getArea())
return 1;
else
return 0;
}
And judging from the link you provided, the getArea method is defined in RectanglePlus only. Since the compiler only sees Relatable it does not know anything about a getArea method at this point and you need to explicitly cast other to RectanglePlus to be able to access it.
Note that you should actually do an instanceof check before casting to avoid a ClassCastException when other is not a RectanglePlus (you don't know if there might be other classes implementing Relatable).
Let me try a non-code related example:
If people have a pet they usually give it a name. So whatever pet you have, one can always ask for its name (cf. hashCode). But they cannot ask you to make it bark (cf. getArea) unless they know that it is a dog.
And you will probably fail to make a cat bark (cf. ClassCastException).

Type Mismatch: cannot convert from PolarAngleComparator to Comparator<Point>

public abstract class Sorter
{
protected Comparator<Point> pointComparator;
private Point lowestPoint;
...
protected void setComparator()
{
if (condtion)
pointComparator = new PolarAngleComparator(lowestPoint);
}
}
public class PolarAngleComparator implements Comparator<Point>
{
private Point referencePoint;
public PolarAngleComparator(Point p)
{
referencePoint = p;
}
public int compare(Point p1, Point p2)
{
if(p1.equals(p2))
{
return 0;
}
else if (p1.equals(referencePoint) || !p1.equals(referencePoint) &&
!p2.equals(referencePoint) && comparePolarAngle(p1, p2) == -1 ||
!p1.equals(referencePoint) && !p2.equals(referencePoint) &&
comparePolarAngle(p1, p2) == 0 && compareDistance(p2, p2) == -1)
{
return -1;
}
else
{
return 1;
}
}
}
The following is my code I'm working on for an assingment. The issue I'm having is occuring in my abstract class when I attempt to assign new PolarAngleComparator(lowestPoint) to pointComparator. The error thrown is Type mismatch: cannot convert from PolarAngleComparator to Comparator. I implemeted Comparator, but I'm still confused as to why this assignment is throwing an error. Any advice or knowledge on this situation/comparators in general would be appreciated. Thanks!
EDIT:
public int comparePolarAngle(Point p1, Point p2)
{
if(crossProduct(p1, p2) == 0)
{
return 0;
}
else if(p1.equals(referencePoint) || crossProduct(p1, p1) > 0)
{
return -1;
}
else
{
return 1;
}
}
private int crossProduct(Point p1, Point p2)
{
int p1x = (int) (p1.getX() - referencePoint.getX());
int p1y = (int) (p1.getY() - referencePoint.getY());
int p2x = (int) (p2.getX() - referencePoint.getX());
int p2y = (int) (p2.getY() - referencePoint.getY());
return ((p1x*p2y)-(p1y*p2x));
}
Define your class as
public class PolarAngleComparator <Point> implements Comparator <Point>{
}
Or replace protected Comparator <Point> pointComparator; with protected Comparator pointComparator; if you don't want to use generics in your class.
Make sure you go through the docs at https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html
Your code compiles fine. You must have messed up the import statements. Make sure you have imported the same class in both places.
Given that your "three dots" below the PolarAngleComparator's constructor represents the implementation of the compare() method (stated from the interface).
public abstract class Sorter {
protected Comparator<Point> pointComparator;
private Point lowestPoint;
protected void setComparator() {
pointComparator = new PolarAngleComparator(lowestPoint);
}
}
public class PolarAngleComparator implements Comparator<Point> {
private Point referencePoint;
public PolarAngleComparator(Point p) {
referencePoint = p;
}
#Override
public int compare(Point o1, Point o2) {
return 0; //TODO: Implement comparator
}
}

How do I check if an object is "empty" or not?

The Cube class have two constructors, one which accepts three parameters that are converted into the tree attributes of the cube, and another one that doesn't require any parameter and therefore creates an "empty" cube. My question is how can a boolean method check if the cubes are valid or empty? Is there a way to do that without the need of checking each one of the attributes?
class Application {
public static void main(String[] args) {
Cube c1 = new Cube(4, 3, 6);
Cube c2 = new Cube();
System.out.println(isNotEmpty(c1));
System.out.println(isNotEmpty(c2));
}
public static boolean isNotEmpty(Cube cube) {
if (/*cube attributes are NOT empty*/) {
return true;
} else {
return false;
}
}
public static class Cube {
private int height;
private int width;
private int depth;
public Cube() {}
public Cube(int height, int width, int depth) {
this.height = height;
this.width = width;
this.depth = depth;
}
public int getHeight() { return height; }
public int getWidth() { return width; }
public int getDepth() { return depth; }
}
}
Since it appears that the only state which a Cube has are the height, width, and depth, then you could actually just use null to represent an empty Cube.
It doesn't make much sense to call a cube with no dimensions a cube in the first place. Using null as a marker might make the most sense.
Either change one (or more) of your int fields to be an Integer Object, or introduce a new Boolean field isSet or get rid of your empty constructor
1) If you use an Integer Object you can test to see if it is null where -as int primitives have a default value of 0
2) If you have a Boolean field you can default it to false and set it to true in your proper constructor
Use a bool flag isEmptyCube in the constructor. At the time of object creation, it will be automatically marked correctly whether it is blank or not.
public static class Cube {
//...
private boolean isEmptyCube;
public Cube() {isEmptyCube = true;}
public Cube(int hight, int width, int depth) {
//...
isEmptyCube = false;
}
public isCubeEmpty() { return isEmptyCube;}
It seems a so tricky question. At first, we have to have any criteria: What is an empty object?. When we have some criteria, even single, we must check it.
From the reason when we are considering the Cube c3 = new Cube(0, 0, 0) like is not empty, so, here is one of ways:
public class CubeApplication {
public static void main(String[] args) {
Cube c1 = new Cube(4, 3, 6);
Cube c2 = new Cube();
Cube c3 = new Cube(0, 0, 0);
System.out.println(c1.isEmpty());
System.out.println(c2.isEmpty());
System.out.println(c3.isEmpty());
}
static class Cube {
private int hight;
private int width;
private int depth;
private boolean isEmpty;
public Cube() {
this.isEmpty = false;
}
public Cube(int hight, int width, int depth) {
this.hight = hight;
this.width = width;
this.depth = depth;
this.isEmpty = true;
}
public boolean isEmpty() {
return this.isEmpty;
}
public int getHight() {
return this.hight;
}
public int getWidth() {
return this.width;
}
public int getDepth() {
return this.depth;
}
}
}
OUTPUT:
true
false
true

The class that implements the interface doesn't work because "Class is not abstract and does not override abstract method...". What is the mistake?

There is an example of "Implementing an Interface" in Java tutorial. I have repeated this example but it doesn't work. NetBeans shows the mistake on te left of RectanglePlus class declaration. And mistake is:
rectangleplus.RectanglePlus is not abstract and does not override
abstract method isLargerThan(rectangleplus.Relatable) in
rectangleplus.Relatable
I did the same as written in tutorial. Why it shows the mistake? Here is my implementation of the project.
The name of the project is RectanglePlus.
The name of the package is rectangleplus.
1st file in the project is Interface Relatable:
package rectangleplus;
public interface Relatable {
int isLarger(Relatable other);
}
2nd file in the project is Main Class RectanglePlus with helper class Point:
package rectangleplus;
public class RectanglePlus implements Relatable {
public int width = 0;
public int height = 0;
public Point origin;
// four constructors
public RectanglePlus() {
origin = new Point(0, 0);
}
public RectanglePlus(Point p) {
origin = p;
}
public RectanglePlus(int w, int h) {
origin = new Point(0, 0);
width = w;
height = h;
}
public RectanglePlus(Point p, int w, int h) {
origin = p;
width = w;
height = h;
}
// a method for moving the rectangle
public void move(int x, int y) {
origin.x = x;
origin.y = y;
}
// a method for computing
// the area of the rectangle
public int getArea() {
return width * height;
}
// a method required to implement
// the Relatable interface
public int isLargerThan(Relatable other) {
RectanglePlus otherRect
= (RectanglePlus)other;
if (this.getArea() < otherRect.getArea())
return -1;
else if (this.getArea() > otherRect.getArea())
return 1;
else
return 0;
}
public static void main(String[] args) {
// TODO code application logic here
}
}
class Point {
int top;
int left;
int x;
int y;
public Point(int t, int l) {
top = t;
left = l;
}
}
Why there is nothing said about abstraction in the tutorial example? Should the tutorial example work without mitakes?
Thank you.
In the interface, you declare the method isLarger but in the class you declare isLargerThan Change one to the other name and it will go fine.
You're not correctly implementing the isLarger() method in the Relatable interface. Rename the isLargerThan(Relatable other) method so it looks like this:
#Override
int isLarger(Relatable other) {
}
It's a good idea to use the #Override annotation, it allows you to catch errors like the one in the question.

Categories