Comparing two object of type circle - java

Create a Java class named “Circle” that implements java.io.Serializable interface and models a circle based on radius. Radius cannot be less than zero. Implement the getter and setter method for radius. Also include an overriding of toString in the circle class. Create the class' comparator which compares two objects of type Circle.
This is what I have so far
import java.io.Serializable;
public class Circle implements Serializable, Comparable<Circle> {
private int radius = 1;
public Circle() {
}
public Circle(int radius) {
setRadius(radius);
}
public void setRadius(int v) {
if (v > 0) {
this.radius = v;
}
}
public int getRadius() {
return this.radius;
}
#Override
public String toString() {
return "Circle{" + "radius=" + radius + '}';
}
#Override
public int compareTo(Circle o) {
//no idea what to put here
}
}
This my comparator class
import java.util.Comparator;
public class CompareCircle implements Comparator<Circle> {
CompareCircle(Circle c1, Circle c2) {
}
#Override
public int compare(Circle o1, Circle o2) {
if (o1.getRadius() > o2.getRadius()) {
return o1.getRadius();
} else {
return o2.getRadius();
}
}
}
My question is did I do this right or no?

First, you don't need to implement Comparable or override compareTo().
According to the documentation, this is what compare() should return:
Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
You can use Integer.compare() to satisfy these requirements:
Returns:
the value 0 if x == y; a value less than 0 if x < y; and a value greater than 0 if x > y
import java.util.Comparator;
public class CompareCircle implements Comparator<Circle> {
#Override
public int compare(Circle o1, Circle o2) {
return Integer.compare(o1.getRadius(), o2.getRadius());
}
}
To compare, you need to create an instance of CompareCircle. You can use it with Collections.max() to retrieve the largest object:
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args){
ArrayList<Circle> list = new ArrayList<Circle>() {{
add(new Circle(4));
add(new Circle(7));
add(new Circle(2));
}};
CompareCircle comp = new CompareCircle();
Circle c = Collections.max(list, comp);
System.out.println(c.getRadius());
}
}
Ouput:
7

As JB pointed out Circle class does not need to implement Comparable if you use comperator:
public class Circle implements Serializable /*, Comparable<Circle> */{
In CompareCircle you can drop the constructor (actually use the default constructor CompareCircle() ).
The compare method should also handle the case of two equal circles:
#Override
public int compare(Circle o1, Circle o2) {
//you may want to consider cases where one circle or both are null
if (o1.getRadius() > o2.getRadius()) {
return o1.getRadius();
} else if (o1.getRadius() == o2.getRadius()) {
return 0;
}
return o2.getRadius();
}
}

Related

generic class that implements comparable

I have been assigned the problem: Write a generic WeightedElement<E,W> class which stores an
element of type E and a weight of type W. It should implement Comparable relying on W's compareTo(). You should enforce that W itself is comparable.
So far I have made the class and implemented comparable but am encountering issue when making the compareTo() method for W. I have:
public class WeightedElement<E, W extends Comparable<W>> {
public E element;
public W weight;
public WeightedElement() {
element = this.element;
weight = this.weight;
}
public int compareTo(W data) {
if (this.weight == data.weight) {
return 0;
} else if (this.weight < data.weight) {
return 1;
} else {
return 1;
}
}
}
I am encountering the issue that when I compare the weights, the weight for data is not found. Also are there any other methods I have to create to properly have a class that implements comparable on one of the variables? Thank you for any help
You have the generics right, but just like WeightedElement itself, you have to call compareTo on the weights -- you can't use < or == to do comparisons.
public class WeightedElement<E, W extends Comparable<W>> implements Comparable<WeightedElement<E, W>> {
private final E element;
private final W weight;
public WeightedElement(E element, W weight) {
this.element = element;
this.weight = Objects.requireNonNull(weight, "'weight' should not be null");
}
#Override
public int compareTo(WeightedElement<E, W> other) {
return other == null ? 1 : weight.compareTo(other.weight);
}
}

Java Sort Custom Objects Using Comparable, Collections.sort()

I have two objects - RightTriangle and Rectangle. Both classes implement "Shape" interface which has 2 abstract methods for area and perimeter. In RightTriangle class I implement comparable and my compareTo returns area:perimeter ratio. I do the same thing in Rectangle class. In the demo I want to sort an array of RightTriangle objects and Rectangle Object using Collections.sort().
Shape Interface Code:
public interface Shape
{
public double getArea();
public double getPerimeter();
}
RightTriangle Code:
public class RightTriangle implements Shape, Comparable<Shape>
{
private int leg1, leg2;
public RightTriangle(int lg1, int lg2)
{
leg1 = lg1;
leg2 = lg2;
}
public double getArea()
{
return (.5*leg1*leg2);
}
public double getPerimeter()
{
return (leg1+leg2 + getHypotenuse());
}
private double getHypotenuse()
{
return (Math.sqrt(Math.pow(leg1,2)+Math.pow(leg2,2)));
}
public int compareTo(Shape obj)
{
return (int)(getArea()/getPerimeter());
}
}
Rectangle Code:
public class Rectangle implements Shape, Comparable<Shape>
{
private int length, width;
public Rectangle(int l, int w)
{
length = l;
width = w;
}
public double getArea()
{
return (width*length);
}
public double getPerimeter()
{
return (2*width + 2*length);
}
public int compareTo(Shape obj)
{
return (int)(getArea()/getPerimeter());
}
}
Demo:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Collections;
public class Demo
{
public static void main (String[] args)
{
RightTriangle right = new RightTriangle(12,14);
Rectangle rect = new Rectangle(7,10);
ArrayList<Shape> al = new ArrayList<Shape>();
al.add(right);
al.add(rect);
Collections.sort(al);
for (int i = 0; i < al.size(); i++)
{
System.out.println (al.get(i));
}
}
}
I am getting an error - "error: no suitable method found for sort(ArrayList). How do I fix this?
Thanks.
1. You need to extend Comparable interface to Shape interface and not traingle and rectangle class as below
public interface Shape extends Comparable<Shape>
{
public double getArea();
public double getPerimeter();
public int compareTo(Shape obj);
}
2. RightTriangle and Rectangle class will only implement Shape interface as
public class RightTriangle implements Shape
public class Rectangle implements Shape
**3. Implement toString method in both RightTriangle and Rectangle class by right click on code ..select source-> generate toString()
#Override
public String toString() {
return "RightTriangle [leg1=" + leg1 + ", leg2=" + leg2 + "]";
}
#Override
public String toString() {
return "Rectangle [length=" + length + ", width=" + width + "]";
}
** See the result i got after correcting your code

Error extending from an abstract class and implementing the Comparable interface

Though the GeometricObject is without errors, the GeoCircle shows an error saying GeoCircle is not abstract and does not override the abstract method compareTo(GeometricObject) though the compareTo method is not written as an abstract class
//abstract class GeometricObject that implements the comparable interface
public abstract class GeometricObject implements Comparable<GeometricObject>
{
public String name;
//sample abstract class of getting area of various shapes
public abstract double getArea();
//sample abstract class for getting perimeter/circumference of various shapes
public abstract double getPerimeter();
//pass in and return name of the object selected in a system out line
public void name(String n)
{
System.out.println("This is a " + n);
}
/** A method for comparing the areas of two geometric objects and returning a boolean for their equals */
public static boolean equalArea(GeometricObject object1,GeometricObject object2)
{
//comparing double to another double
return object1.getArea()==object2.getArea();
}
// a method to find the bigger between two GeometricObjects and returning a String statement
public static void max(GeometricObject g1, GeometricObject g2)
{
if(g1.compareTo(g2)>0)
System.out.println("Object 1 is larger ");
else if (g1.compareTo(g2)<0)
System.out.println("Object 2 is larger ");
else
System.out.println("Objects are the same ");
}
// an override of the compareTo method from the implemented comparable interface
public int compareTo(GeometricObject g1, GeometricObject g2)
{
if(g1.getArea()>g2.getArea())
return 1;
else if (g1.getArea()<g2.getArea())
return -1;
else
return 0;
}
}
//a class for calculating circumference and area of a circle extended from GeometricObject
public class GeoCircle extends GeometricObject implements Comparable<GeoCircle>
{
public String name;
public double radius;
//constructor for only inputting radius of the circle
public GeoCircle(double r)
{
radius = r;
}
// 2ndconstructor taking a name for the shape and radius of the circle
public GeoCircle(String n, double r)
{
name = n;
radius = r;
}
//method to get area of the shape with previously passed in radius
public double getArea()
{
return Math.PI*Math.pow(radius,2);
}
//method to get circumference of the circle with radius previously given
public double getPerimeter()
{
return 2*Math.PI*radius;
}
//a compareTo method
public int compareTo(GeoCircle obj)
{
if (this.getArea() > obj.getArea())
return 1;
else if (this.getArea() < obj.getArea())
return -1;
else
return 0;
}
}
public int compareTo(GeometricObject g1, GeometricObject g2)
{
if(g1.getArea()>g2.getArea())
return 1;
else if (g1.getArea()<g2.getArea())
return -1;
else
return 0;
}
does not correctly override compareTo. compareTo is expected to take one argument and compare this to that argument. This could be implemented as
#Override public int compareTo(GeometricObject g) {
return Double.compare(getArea(), g.getArea());
}
For reference, adding the #Override annotation verifies that a method correctly overrides a superclass method, which would have been caught.
You should use generics in base class:
public abstract class GeometricObject<T extends GeometricObject> implements Comparable<T> {
...
// an override of the compareTo method from the implemented comparable interface
public int compareTo(T that) {
if(this.getArea()>that.getArea())
return 1;
else if (this.getArea()<that.getArea())
return -1;
else
return 0;
}
}
//a class for calculating circumference and area of a circle extended from GeometricObject
public class GeoCircle extends GeometricObject<GeoCircle> {
...
#Override // Remove this method if it doesn't differ from parent implementation
public int compareTo(GeoCircle that) {
...
}
}
Comparable interface is extremely strict. Much better solution would be implementing separate comparator and remove Comparable declaration from the base class:
class GeometricObjectAreaComparator implements Comparator<GeometricObject> {
#Override
public int compare(GeometricObject o1, GeometricObject o2) {
...
}
}

Produce sorted arraylist from unsorted arraylist in 1 interation?

Say I have arraylist A and to compare 2 objects of A I do a.getDistanceFromPlayer() < b.getDistanceFromPlayer().
I want to now have list B which will have all of A's objects, but sorted where the first object is closest to player, and last object is furthest.
What might be the fastest way to do this?
Thanks
Have A implement Comparable and then define the method compareTo(Object other) like so:
public int compareTo(Object other) {
if( this.getDistanceFromPlayer() < other.getDistanceFromPlayer() ) {
return -1;
} else if( this.getDistanceFromPlayer() > other.getDistanceFromPlayer()) {
return 1;
}
return 0;
}
Now you can call Collections.sort() on your list of objects
Use Collections.sort with a custom comparator.
eg.
public class DistanceComparator implements Comparator<Integer>{
#Override
public int compare(YourObject o1, YourObject o2) {
if (o1.getDistanceFromPlayer() > o2.getDistanceFromPlayer())
{
return 1;
}
else if (o1.getDistanceFromPlayer() < o2.getDistanceFromPlayer())
{
return -1;
}
return 0;
}
}
Then in your program, call
Collections.sort(YourArrayInstance, new DistanceComparator())
You should make your class implement Comparable.
Then you can use Collections.sort() to sort your List.
If you want a sorted List AND an unsorted List, you'll have to make a copy.
Another option is to create a Comparator.
If you read the documentation for Collections, you'll see it has two sort methods.
One bases the sort on the objects' compareTo method (ie their "natural order").
The other bases the sort on a Comparator that is passed as the second argument.
Here's a link to another question that provides an example implementation of Comparable:
Example implementation of Comparable
Use a Custom Comparator :
B = Collections.sort(A, new CustomComparator());
public class CustomComparator implements Comparator<ClassA> {
#Override
public int compare(final ClassA a, final ClassA b) {
//Make sure you check that neither a nor b are null..
//..
if (a.getDistanceFromPlayer() < b.getDistanceFromPlayer()) {
return 1;
} else if (a.getDistanceFromPlayer() > b.getDistanceFromPlayer()) {
return -1;
}
return 0;
}
}
You can use a custom Comparator and sort your ArrayList, like this:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Main {
public static class Player {
private final float distance;
public Player (final float position) {
this.distance = position;
}
public float getDistanceFrom () {
return distance;
}
#Override
public String toString() {
return "Player [distance=" + distance + "]";
}
}
public static void main(String[] args) throws Exception {
final ArrayList<Player> players = new ArrayList<Player> ();
players.add (new Player (2));
players.add (new Player (5));
players.add (new Player (-3));
players.add (new Player (1));
Collections.sort(players, new Comparator<Player> () {
#Override
public int compare(Player o1, Player o2) {
final float distance1 = o1.getDistanceFrom();
final float distance2 = o2.getDistanceFrom();
return (int) Math.signum (distance1 - distance2);
}
});
System.out.println(players);
}
}
And a fiddle for it.

Java: Order a collection according to subtype

Not quite sure how I should attack this. I need to create a Comparator for a class called Record. These records have a time I will use, but if the time is the same, I need to order them depending on their type. Say for example we have the following Record subtypes:
AaRecord
BbRecord
CcRecord
DdRecord
Now, given a collection with a number of these, I need to order them so that for example all CcRecord come before BbRecord followed by AaRecord and finally DdRecord. What is a good and clean way of doing this?
Just to be clear, I can't use the names of the types to do this, as they could be anything. It's going to be used to process a list of records in the correct order.
public class RecordComparator implements Comparator<Record>
{
#Override
public int compare(Record x, Record y)
{
// First compare times
int result = x.getTime().compareTo(y.getTime());
if(result != 0)
return result;
// Then somehow compare types...
}
}
You could define a Map<Class, Integer> containing the sort orders for all the types, and then do this:
#Override
public int compare(Record x, Record y)
{
// First compare times
int result = x.getTime().compareTo(y.getTime());
if(result != 0)
return result;
// sortOrders is your map
return sortOrders.get(x.getClass()).compareTo(sortOrders.get(y.getClass()));
}
Or something like that.
Keep in mind that it doesn't have to be integers.
How about having a method that establishes order of the type, for example:
public abstract class Record
{
public abstract int getRecordOrdinal();
}
public abstract class AaRecord extends Record
{
#Override
public int getRecordOrdinal() {
return 1;
}
}
public abstract class BbRecord extends Record
{
#Override
public int getRecordOrdinal() {
return 2;
}
}
//etc
public class RecordComparator implements Comparator<Record>
{
#Override
public int compare(Record x, Record y)
{
// First compare times
int result = x.getTime().compareTo(y.getTime());
if(result != 0)
return result;
return y.getRecordOrdinal() - x.getRecordOrdinal();
}
}
Although this sounds like you let us do your work, here is the outline of how to solve the problem:
(1) Extend your Record class for one abstract method getSortOrder()
public abstract class Record {
public abstract int getSortOrder();
}
(2) Implement this method in your your subtypes AaRecord, BbRecord, CcRecord, ... as how you want them to be ordered, e.g.
public class AaRecord {
#Override
public int getSortOrder() {return 0; }
}
public class BbRecord {
#Override
public int getSortOrder() {return 1; }
}
And so on.
(3) RecordComparator implementation
public class RecordComparator implements Comparator<Record>
{
#Override
public int compare(Record x, Record y)
{
// First compare times
int result = x.getTime().compareTo(y.getTime());
if(result != 0)
return result;
// Compare types
return x.getSortOrder() - y.getSortOrder();
}
}
Alternatively, you can define an extra interface Sortable { int getSortOrder(); } and have Record implement it.

Categories

Resources