I am not sure how to implement a comparable interface into my abstract class. I have the following example code that I am using to try and get my head around it:
public class Animal{
public String name;
public int yearDiscovered;
public String population;
public Animal(String name, int yearDiscovered, String population){
this.name = name;
this.yearDiscovered = yearDiscovered;
this.population = population; }
public String toString(){
String s = "Animal name: "+ name+"\nYear Discovered: "+yearDiscovered+"\nPopulation: "+population;
return s;
}
}
I have a test class that will create objects of type Animal however I want to have a comparable interface inside this class so that older years of discovery rank higher than low. I have no idea on how to go about this though.
You just have to define that Animal implements Comparable<Animal> i.e. public class Animal implements Comparable<Animal>. And then you have to implement the compareTo(Animal other) method that way you like it.
#Override
public int compareTo(Animal other) {
return Integer.compare(this.year_discovered, other.year_discovered);
}
Using this implementation of compareTo, animals with a higher year_discovered will get ordered higher. I hope you get the idea of Comparable and compareTo with this example.
You need to:
Add implements Comparable<Animal> to the class declaration; and
Implement a int compareTo( Animal a ) method to perform the comparisons.
Like this:
public class Animal implements Comparable<Animal>{
public String name;
public int year_discovered;
public String population;
public Animal(String name, int year_discovered, String population){
this.name = name;
this.year_discovered = year_discovered;
this.population = population;
}
public String toString(){
String s = "Animal name: "+ name+"\nYear Discovered: "+year_discovered+"\nPopulation: "+population;
return s;
}
#Override
public int compareTo( final Animal o) {
return Integer.compare(this.year_discovered, o.year_discovered);
}
}
While you are in it, I suggest to remember some key facts about compareTo() methods
CompareTo must be in consistent with equals method e.g. if two objects are equal via equals() , there compareTo() must return zero otherwise if those objects are stored in SortedSet or SortedMap they will not behave properly.
CompareTo() must throw NullPointerException if current object get compared to null object as opposed to equals() which return false on such scenario.
Read more: http://javarevisited.blogspot.com/2011/11/how-to-override-compareto-method-in.html#ixzz4B4EMGha3
Implement Comparable<Animal> interface in your class and provide implementation of int compareTo(Animal other) method in your class.See This Post
You would need to implement the interface and define the compareTo() method.
For a good tutorial go to - Tutorials point link
or
MyKongLink
Emp class needs to implement Comaparable interface so we need to Override its compateTo method.
import java.util.ArrayList;
import java.util.Collections;
class Emp implements Comparable< Emp >{
int empid;
String name;
Emp(int empid,String name){
this.empid = empid;
this.name = name;
}
#Override
public String toString(){
return empid+" "+name;
}
#Override
public int compareTo(Emp o) {
if(this.empid==o.empid){
return 0;
}
else if(this.empid < o.empid){
return 1;
}
else{
return -1;
}
}
}
public class JavaApplication1 {
public static void main(String[] args) {
ArrayList<Emp> a= new ArrayList<Emp>();
a.add(new Emp(10,"Mahadev"));
a.add(new Emp(50,"Ashish"));
a.add(new Emp(40,"Amit"));
Collections.sort(a);
for(Emp id:a){
System.out.println(id);
}
}
}
Possible alternative from the source code of Integer.compare method which requires API Version 19 is :
public int compareTo(Animal other) {
return Integer.valueOf(this.year_discovered).compareTo(other.year_discovered);
}
This alternative does not require you to use API version 19.
Use a Comparator...
public class AnimalAgeComparator implements Comparator<Animal> {
#Override
public int compare(Animal a1, Animal a2) {
...
}
}
This thing can easily be done by implementing a public class that implements Comparable. This will allow you to use compareTo method which can be used with any other object to which you wish to compare.
for example you can implement it in this way:
public String compareTo(Animal oth)
{
return String.compare(this.population, oth.population);
}
I think this might solve your purpose.
Related
Let's say I have an object like:
public class Fruit{
private String name;
private int quantity;
Fruit(){}
Fruit(String name, int quantity){
this.name = name;
this.quantity= quantity;
}
public int getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And I want to sort an array full of Fruit objects alphabetically by name. My initial thought, Arrays.sort(a.getName()); wouldn't work, because .getName() only works on individual objects. One idea I had was put all the names into an array, sort those alphabetically, then run a loop to sort the objects using this list, but that seems absurdly cumbersome.
Any ideas? As you can tell, I'm very new to working with objects in this manner.
Either you make your Fruit class Comparable by implementing the compareTo method, or you provide a custom Comparator to the Arrays.sort method:
Arrays.sort(fruits, Comparator.comparing(Fruit::getName));
This uses the Comparator.comparing method.
I recommend you redefine your Fruit class to implement Comparable<Fruit> so that you can easily sort a Fruit[] by each elements' respective name field:
public class Fruit implements Comparable<Fruit> {
// Code here...
#Override
public int compareTo(Fruit fruit) {
return name.compareTo(fruit.name);
}
}
Now, you can call Arrays#sort on Fruit[] and it will sort them lexicographically by name.
You don't need to make your Fruit class implement Comparable<Fruit>; you can do it by passing a custom Comparator to the array, like this:
Array<Fruit> sortedArray = sort(fruitArray, new Comparator<Fruit>() {
public int compare(Fruit left, Fruit right) {
return left.name.compareTo(right.name);
}
public int equals(Object obj) { return 0; /* you can ignore this */ }
});
It seems odd that this is not working as I expected. I wrote a simple java class that implements Comparable interface and override the compareTo() method. However, It doesn't let me pass arguments of specific type other than Object. I looked on other guys' codes online which they did used other typed objects and I copied their code into eclipse and still I got the same error.
My question is; what I have to do to compare this object with object of type lets say Person. I do have the same issue with Comparator Interface (compare() method).
This code is the one I found it online.
public class Person implements Comparable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return this.age;
}
public String getName() {
return this.name;
}
#Override
public String toString() {
return "";
}
#Override
public int compareTo(Person per) {
if(this.age == per.age)
return 0;
else
return this.age > per.age ? 1 : -1;
}
public static void main(String[] args) {
Person e1 = new Person("Adam", 45);
Person e2 = new Person("Steve", 60);
int retval = e1.compareTo(e2);
switch(retval) {
case -1: {
System.out.println("The " + e2.getName() + " is older!");
break;
}
case 1: {
System.out.println("The " + e1.getName() + " is older!");
break;
}
default:
System.out.println("The two persons are of the same age!");
}
}
}
You need to use generics to provide a specific type.
public class Person implements Comparable<Person> { // Note the generic to Person here.
public int compareTo(Person o) {}
}
The Comparable interface is defined something like this,
public interface Comparable<T> {
public int compareTo(T o);
}
You can make use of generics to use custom object types. Change your class definition from
public class Person implements Comparable {
to
public class Person implements Comparable<Person> {
Now you should be able to pass Person object to your compareTo method as mentioned here:
#Override
public int compareTo(Person personToCompare){
Learn more about generics here:
https://docs.oracle.com/javase/tutorial/java/generics/types.html
The graphic below shows a compilation error involving my if-else conditional when attempting to implement the compareTo() method located in my Tool class. I am uncertain of the issue, as it would appear that the method is public and within my Tool class (from which the two objects being compared are constructed).
public interface Product {
public abstract String getName();
public abstract double getCost();
}
public abstract class Vehicle implements Product {
private String name;
private double cost;
public Vehicle(String name, double cost) {
this.name = name;
this.cost = cost;
}
public String getName() {
return name;
}
public double getCost() {
return cost;
}
}
public class Car extends Vehicle {
public Car(String s, double d) {
super(s, d);
}
}
public class Truck extends Vehicle {
public Truck(String s, double d) {
super(s, d);
}
}
public class Tool implements Product, Comparable<Product> {
private String name;
private double cost;
public Tool(String name, double cost) {
this.name = name;
this.cost = cost;
}
public String getName() {
return name;
}
public double getCost() {
return cost;
}
public int compareTo(Product obj) {
if (getCost() < obj.getCost()) {
return -1;
} else if (getCost() == obj.getCost()) {
return 0;
} else {
return 1;
}
}
}
import java.util.*;
public class InventoryDemo
{
public static void main(String [] args) {
ArrayList<Product> list = new ArrayList<Product>();
list.add(new Car("Jagur", 1000000));
list.add(new Car("Neon", 17000));
list.add(new Tool("JigSaw", 149.18));
list.add(new Car("Jaguar", 110000));
list.add(new Car("Neon", 17500));
list.add(new Car("Neon", 17875.32));
list.add(new Truck("RAM", 35700));
list.add(new Tool("CircularSaw", 200));
list.add(new Tool("CircularSaw", 150));
list.add(new Tool("saw1", 200));
list.add(new Tool("saw2", 150));
if(list.get(9).compareTo(list.get(10)) == 0) {
System.out.println("\nThey are the same size using compareTo().");
} else {
System.out.println("\nThey are not the same size using compareTo().");
}
}
}
The Problem is your list is of type List<Product>, but product does not implement the Comparable interface, therefore this type does not implement the method.
Make
public interface Product extends Comparable<Product> {
public abstract String getName();
public abstract double getCost();
}
Your Product interface doesn't extend Comparable<Product> which adds
int compareTo(Product other);
list is declared as ArrayList<Product>, so list.get(9) will return you Product object.
To resolve issue you have either to make Product extend Comparable<Product> and implement method in Vehicle, or, maybe, use equals() method instead, overriding default implementation. Actually the second way is preferrable, because equals() method checks whether objects are equal, while compareTo() tells you if this object is greater then other, or other is greater than this, or none of that is applicable - which makes equals() usage more semantically correct in your case.
Your list is an ArrayList<Product>, so list.get(9) returns a Product.
The compareTo(Product) method is not defined in interface Product. It's defined in class Tool, but you're trying to call it on a Product, which is not (always) a Tool.
To solve this: Make your interface Product extend Comparable<Product>:
interface Product extends Comparable<Product> {
Ofcourse that means that any (non-abstract) class that implements interface Product must also have a public int compareTo(Product obj) method.
The list item you are trying to call compareTo() on is a Product, because the list is declared as a list of Products:
ArrayList<Product> list = new ArrayList<Product>();
When accessing items in the list, Java is only aware that the items implement the Product interface, irrespective of whether the actual class also implements Comparable.
One solution is to define Product as extending Comparable:
public interface Product extends Comparable<Product> {
public abstract String getName();
public abstract double getCost();
}
I have an abstract class Person and and interface comparable, which is also used for some other part of the program. Currently I have a method compareTo() in Person. When I try to compile, I get :
The type Student must implement the inherited abstract method
Comparable<Person>.compareTo(Person, Person)
What exactly do I have to do? I don't wont to implement this method in any of the subclasses, because I need this method for all of them, Student, Tutor, Professor, etc... Is there a better way of doing this?
Interface:
interface Comparable<Element> {
public int compareTo(Element nodeA, Element nodeB);
}
Abstract class Person:
abstract class Person implements Comparable<Person> {
protected String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
public String toString() {
return name;
}
public int compareTo(Person personB) {
int comp = this.name.compareTo(personB.getName());
return comp;
}
}
And class Student
class Student extends Person implements Comparable<Person> {
private int id;
public Student(String name, int id) {
super(name);
this.id = id;
}
public int getID() {
return id;
}
public void setID(int newID) {
id = newID;
}
public String toString() {
return id + ", " + name;
}
}
Change your interface from:
interface Comparable<Element>
{
public int compareTo(Element nodeA, Element nodeB);
}
to:
interface Comparable<Element>
{
public int compareTo(Element nodeA);
}
And make your Person class be defined as:
abstract class Person implements Comparable<? extends Person> { /* ... */ }
And make your Student (and other Person-subclasses be):
class Student extends Person { /* ... */ }
That is all.
Your Comparable interface has a method compareTo(Element nodeA, Element nodeB). This method is not defined in Student, and it's not defined in Person either. Person has the following method:
public int compareTo(Person personB)
, which doesn't override compareTo(Person nodeA, Person nodeB)
Why are you redefining the standard java.util.Comparable interface?
You should implement the method as it appears in the interface, i.e. with two arguments
public int compareTo(Person nodeA, Person nodeB)
To avoid such problems in the future use the #Override annotation:
#Override
public int compareTo(Person nodeA, Person nodeB)
This will cause a compilation error if you try to override a method, but make a mistake in its signature.
Also, consider using Java's standard Comparable.
Your Comparable<Element> class declares a method public int compareTo(Element nodeA, Element nodeB);, but in your Person class, you implement public int compareTo(Person personB), which is not the same method signature.
You need to either implement public int compareTo(Person personA, Person personB), or alter your Comparable<Element> class's method definition to be public int compareTo(Element other); to override the core Comparable class's compareTo method.
Also, as #murat mentions below in the comment, using the #Override annotation would help you out (assuming you're on Java version 1.5 or higher). If you add #Override to a method that you're not actually overriding from a superclass (such as your two-argument compareTo method), then it will be a compiler error.
You need to implement
public int compareTo(Person nodeA, Person nodeB)
In your Person class. Currently you only have:
public int compareTo(Person personB)
You need to create a compareTo method in the Student class.
interface Comparable<Element> {
public int compareTo(Element nodeA, Element nodeB);
}
It makes sense if it was either:
interface Comparator<Element> { //comparator compares two instances of same type
public int compare(Element nodeA, Element nodeB);
}
or (has to be something like this for your case):
interface Comparable<Element> { //comparable compares itself with another instance of same type
public int compareTo(Element that);
}
But for both cases, you should use the standard Java interfaces: Even though you are only using Comparable also see Comparator.
I have this Player class which implements the Comparable interface. Then I have an ArrayList of Players. I'm trying to use binarySearch() on the list of Players to find one Player, but Java is giving me a "cannot find symbol: method binarySearch(java.util.ArrayList< Player>,Player)".
This the Player class:
class Player implements Comparable {
private String username;
private String password;
Statistics stats;
//Constructor, creates a new Player with a supplied username
Player(String name) {
username = name;
password = "";
stats = new Statistics();
}
//Accessor method to return the username as a String
String getName() {
return username;
}
String getPassword() {
return password;
}
void setPassword(String newPass) {
password = newPass;
}
//Method to change the username
void setName(String newName) {
username = newName;
}
public int compareTo(Object o) {
return username.compareTo(((Player)o).username);
}
}
Weird thing, when I try Collections.sort() on this same list, it works.
Use are using generics inconsistently. Take heed of the compiler warnings. Always supply generic arguments (or never supply them).
Instead of:
class Player implements Comparable {
[...]
public int compareTo(Object o) {
Use
class Player implements Comparable<Player> {
[...]
public int compareTo(Player o) {
The rules of generics are difficult enough without the complication of rare types. So, typically the language spec gives up if you mix them up.
As long as you are implementing Comparable, you can make compareTo() consistent with equals() by also overriding equals() and hashCode(). This is particularly easy in this case, as you can simply delegate to String. Moreover, it's convenient if you ever need a Map containing instances of Player:
class Player implements Comparable<String> {
private String username;
private String password;
// ...
#Override
public int compareTo(String name) {
return username.compareTo(name);
}
#Override
public boolean equals(Object obj) {
return obj instanceof Player
&& username.equals(((Player)obj).username);
}
#Override
public int hashCode() {
return username.hashCode();
}
}