Using compareTo in Java to Sort - java

Basically i'm attempting to write a compareTo that does the comparison based on the value of compareByWord. If compareByWord is true, I want it to compare based on the word, but if it's false, I want it to compare based on count.
class WordCount implements Comparable //Error saying WordCount must implement the inherited abstract method Comparable.compareto (Object)
{
String word;
int count;
static boolean compareByWord;
public WordCount(String aWord)
{
setWord(aWord);
count = 1;
}
private void setWord(String theWord)
{
word=theWord;
}
public void increment()
{
count+=1;
}
public static void sortByWord()
{
compareByWord = true;
}
public static void sortByCount()
{
compareByWord = false;
}
public String toString()
{
String result = String.format("%s (%d)",word, count);
return result;
}
public String getWord()
{
return word;
}
public int getCount()
{
return count;
}
#Override
public int compareTo(WordCount other) { //Error saying compareTo (WordCount) of type WordCount must override or implement a supertype method.
if (compareByWord == true)
{
return word.compareTo(other.getWord());
}
if (compareByWord == false)
{
return count.compareTo(other.getCount()); //Error saying it cannot invoke compareTo int on primitive type int.
}
return 0;
}
}
My class was perfect before I tried to implement this, not sure where I'm going wrong here. Any and all help is much appreciated.

Change the declaration to
class WordCount implements Comparable<WordCount> { // generic version
The method signature in Comparable<WordCount> is compareTo(WordCount obj) while for the raw version it's compareTo(Object obj).
With the usage of #Override, the compiler makes sure that you actually override the parent method. And the problem is that compareTo(WordCount obj) does not override compareTo(Object obj).

must implement the inherited abstract method Comparable.compareto (Object)
So pass Object, not WordCount. Now you're trying to overload this function, not override.

Use Integer count not int count. Integer is an object which implements Comparable whereas int is a primitive as the error message describes. For javadocs:
public final class Integer
extends Number
implements Comparable<Integer>
Make sure you change your accessor methods to use Integer as well of course.
That will take care of your final error.

Related

Implementing a functional interface via method reference

First I got a class named after my Chinese name
public class Yxj<T> {
private T[] data;
private int size = 0;
private final Comparator<? super T> comparator;
public Yxj(Comparator<? super T> c) {
data= (T[]) new Object[16];
comparator = c;
}
public void addItem(T t){
data[size++] = t;
}
public int sort(){
return comparator.compare(data[0], data[1]);
}
public T[] getData(){
return data;
}
}
in which a Comparator resides,then I defined a Norwich keeping a field order and setter and getter of it, finally there's a method used to implement the compare(T t1,T t2) in Comparator.
public class Norwich {
private int order;
public Norwich(int o) {
order = o;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public int compareOrder(Norwich n) {
if (order > n.getOrder()) {
return 2;
} else if (order == n.getOrder()) {
return 0;
} else {
return -3;
}
}
}
then here comes the main method
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
norwichYxj.addItem(new Norwich(9));
norwichYxj.addItem(new Norwich(1));
System.out.println(norwichYxj.sort());
so what I'm interested in is that, why does not the method compareOrder keep the same parameters as the compare in Comparator but it can still work correctly?
It is simple. You have passed through the constructor your implementation of the Comparator to be used for comparing.
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
Remember Comparator is nothing else than an interface. Since it is a functional interface, it can be represented through a lambda expression or a
method reference (as you did). The way you can pass the Comparator in the full form is as follows. Note the usage of the compareOrder method:
Yxj<Norwich> norwichYxj = new Yxj<>(new Comparator<>() {
#Override
public int compare(Norwich o1, Norwich o2) {
return o1.compareOrder(o2); // usage of compareOrder
}
});
This can be shortened to a lambda expression:
Yxj<Norwich> norwichYxj = new Yxj<>((o1, o2) -> o1.compareOrder(o2));
It can be shortened again to a method reference:
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
Now you can see it can be represented in this way though the method compareOrder accepts only one formal parameter. The first parameter of the Comparator#compare method is the one invoking the compareOrder method and the second parameter is the one being passed to the compareOrder method.
Learn more here: https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
Additionally, the classes you have constructed look a bit odd. Though the other answer doesn't in fact answer your question, it can lead you to a better code: Implementing a functional interface via method reference
class Yxj
The paramter T of your class Yxj should have more restrictions if you want to compare/sort in this class with T then say T must be comparable.
If your T array grows then don't implement your own growing array but use ArrayList instead which does that for you
If you do the first you don't need the Comperator anymore
Your methode sort only sorts the first and second element so you will get problems. If the data is shorter you will get an ArrayIndexOutOfBoundsException if it is longer it won't sort the rest of elements. So with a Collection you could simple use Collections.sort(data);
public class Yxj<T extends Comparable<T>> {
private final List<T> data;
public Yxj() {
this.data = new ArrayList<>();
}
public void addItem(T t){
data.add(t);
}
public void sort(){
Collections.sort(data);
}
public List<T> getData(){
return data;
}
public void print(){
System.out.println(data);
}
}
class Norwich
If you done the above know your Norwich class must implement the Comparable interface so you can compare Norwich instances with the methode compareTo which also will be called each time you or the API ask directly or indirectly to compare to Norwich instances like for sorting ect.
public class Norwich implements Comparable<Norwich> {
private int order;
public Norwich(int o) {
this.order = o;
}
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
#Override
public int compareTo(Norwich other) {
return this.order - other.order;
}
#Override
public String toString() {
return "Norwich{" +
"order=" + order +
'}';
}
}
Main
Done? Perfect, then your main could be looks like this
public static void main(String[] args) {
Yxj<Norwich> norwichYxj = new Yxj<>();
norwichYxj.addItem(new Norwich(9));
norwichYxj.addItem(new Norwich(1));
norwichYxj.sort();
norwichYxj.print();
}

How to cast integer to some generic type?

I have a class MyClass and its super-class MySuperClass.
MySuperClass is from a standard library, so its codes cannot be changed.
As per the user requirement, the method name myMethod() of MyClass cannot be changed as well.
Unluckily, the same name MyClass is already in MySuperClass, and those codes are not what I want. I used #Override to override those codes (Thanks for the help from Matteo NNZ who suggested me for this fix in the case of having various generic types).
However, I need to cast keyInt to type K such that I can call the mySubMethod(). Below is my code:
MyClass
public class MyClass<K,V> extends MySuperClass {
// the name "myMethod" are not allowed to be modified
public boolean myMethod(K key) { // if key is NOT integer, Main.java will call this method
mySubMethod(key);
return false;
}
#Override // This is a fix; To Override myMethod(int index) of MySuperClass.
public boolean myMethod(int keyInt) { // if key is integer, Main.java will call this method
K key = (K) keyInt; // <-- I have error here
mySubMethod(key);
return false;
}
public boolean mySubMethod(K key) {
System.out.println("I want to call this");
return false;
}
}
MySuperClass
public class MySuperClass { // codes of MySuperClass are not allowed to be modified
public boolean myMethod(int index) {
System.out.print("Shouldn't be called.");
return false;
}
}
To call MyClass, in Main.java I will create new instances for either MyClass<Integer, String> or MyClass<String, String>. But currently I got error message "Cannot cast from int to K".
I tried to fix the error by using if(key instanceof Integer){ /** blahblahblah */}, but it doesn't work since KeyInt is already an integer when the method is called. How can I fix this?
Do you want this result?
public class MyClass<K,V> extends MySuperClass {
// the name "myMethod" are not allowed to be modified
public boolean myMethod(K key) { // if key is NOT integer, Main.java will call this method
mySubMethod(key);
return false;
}
#Override // This is a fix; To Override myMethod(int index) of MySuperClass.
public boolean myMethod(int keyInt) { // if key is integer, Main.java will call this method
// K key = (K) keyInt; // <-- I have error here
mySubMethod(keyInt);
return false;
}
public <T> boolean mySubMethod(T key) {
System.out.println("I want to call this");
return false;
}
}

Use Comparable Interface to Sort a Generic Linked List

I want to sort my self implemented Linked List Using Comparable Interface with Java .I need to implement the compareTo method :
Here is the code for my class ListElement :
public class ListElement implements Comparable<ListElement> {
public Object wert;
public ListElement nachFolger;
public ListElement(Object wert , ListElement nachFolger) {
this.wert=wert;
this.nachFolger=nachFolger;
}
#Override
public int compareTo(ListElement a) {
if(this.nachFolger.wert - a.wert) {
return 1;
}
return 0;
}
}
But I get an error , any recommendations ?
You are trying to subtract to references of type Object.
Your element type should implement Comparable:
public class ListElement<T extends Comparable<T>> implements Comparable<ListElement<T>> {
public T wert;
public ListElement<T> nachFolger;
public ListElement(T wert, ListElement<T> nachFolger) {
this.wert=wert;
this.nachFolger=nachFolger;
}
#Override
public int compareTo(ListElement<T> a) {
return wert.compareTo(a.wert);
}
}
In Java, subtract operation only applies to numeric literals (and auto-unboxed numeric objects). As you are trying to use it on non numeric Object type, you are getting the error. If you want to compare two wert values, you can do the following:
Change the type to number from Object so that you can compare, e.g.:
public Object wert;
#Override
public int compareTo(ListElement a) {
return wert.compareTo(a.wert);
}
Change the type to Comparable so you can use compareTo on two wert objects
public Comparable wert;
#Override
public int compareTo(ListElement a) {
return wert.compareTo(a.wert);
}

Does the equals method work with objects? If so, how?

I have a program that is zoo and in the zoo there are branched subgroups of animals that are reptiles. When I do an equals method the main program compiles and it runs. I'm confused how does java know to use the equals method if I'm comparing objects and not specifically int or String?
public class Zoo {
public static void main(String[]args) {
Animal a=new Animal("Bob");
Reptile komodo= new Reptile("Snakey");
komodo.bask();
a.size=3;
komodo.size=5;
System.out.println(a);
System.out.println(komodo);
Turtle t= new Turtle("Slowy");
t.hide();
t.size=6;
t.numlegs=4;
System.out.println(t);
System.out.println(t.equals(komodo));
}
}
public class Animal {
public String name;
public boolean equals(Animal other) {
return other.size==this.size;
}
public Animal(String s) {
name=s;
}
public void setName(String n) {
this.name=n;
}
public void eat(String meal) {
System.out.println("chump chump yummy "+meal);
}
public int size;
public String toString() {
return "I am "+name+" and I'm "+size+" cm long";
}
}
public class Reptile extends Animal {
public Reptile(String n) {
super(n);
numlegs=0;
}
public Reptile(String n, int l) {
super(n);
numlegs=l;
}
public void bask() {
System.out.println("basking...");
}
public String toString() {
return super.toString()+numlegs+" legs";
}
public int numlegs;
}
public class Turtle extends Reptile {
public Turtle(String n) {
super (n,4);
shellColor="Brown";
}
public void hide() {
System.out.println("you cant see me");
}
public String toString() {
return super.toString()+" and my shell is"+ shellColor;
}
public String shellColor;
public void bask() {
super.bask();
System.out.println("turtle is basking...");
}
}
You're not overriding the Object#equals method, but overloading it. In your method declaration you use Animal type instead of Object:
public boolean equals(Animal other)
A good overriding of the method would be using the instanceof operator. Showing an example:
#Override
public boolean equals(Object other) {
if(other instanceof Animal) {
Animal otherAnimal = (Animal)other;
//comparison logic...
}
return false;
}
More info on the subject:
Best practices regarding equals: to overload or not to overload?
Overriding Object.equals VS Overloading it
For your question on how java knows how to compare objects,
you need to override the equals method
public boolean equals(Object other){
// return true or false based on your logic
}
While comparing, equals method is used.
You can have a look at this good tutorial which explains the significance of the equals method.
http://www.thejavageek.com/2013/06/26/what-is-the-significance-of-equals-method-in-java/
Also, only overriding equals is not enough if you are using objects into collections those use hashing. You will find a good tutorial at
http://www.thejavageek.com/2013/06/28/significance-of-equals-and-hashcode/
Every class inherits the Object class silently. And the Object class has a equals method. So if any class doesn't override the equals method then it will use the default implementation of Object.equals.
From the doc
The equals method for class Object implements the most discriminating
possible equivalence relation on objects; that is, for any non-null
reference values x and y, this method returns true if and only if x
and y refer to the same object (x == y has the value true).
From the source code of Object.equals
public boolean equals(Object obj) {
return (this == obj);
}
So If any object doesn't have it's own implementation of equals then the equals method will simply check if the object reference is same or not.
So get a desired result from equals you need to implement by your own as alread suggested in other answer

Java interface method - parameter and return value type as child of Number

I am not very skilled in Java so I consider my question as basic. I am writing an interface for something like ArrayResult. There will be methods add and get.
Problem is that ArrayResult can obtain values of Integer or Double. So I need to define methods in interface more generally. I figured out that it is possible to have something like this for get method:
public <N extends Number> N get(Integer index);
Is that correct? I believe this means that get method can return anything what extends Number Object. What sytax to use for add method?
public void add(Number value);
This is not what I want since add(Integer value) doesnt override the interface method.
I guess what you want is
interface ArrayResult<N extends Number> {
public N get(Integer index);
public void add(N value);
}
Then you can write two separate specific implementers
class IntegerResult implements ArrayResult<Integer> {
#Override
public void add(Integer value) {
}
#Override
public Integer get(Integer index) {
return null;
}
}
class DoubleResult implements ArrayResult<Double> {
#Override
public void add(Integer value) {
}
#Override
public Double get(Double index) {
return null;
}
}
References:
Bounded Type Parameters
interface ArrayResult<N extends Number> {
public N get(Integer index);
public void add(N value);
}
Just return Number.
Number get(Integer index);
This will also allow you to return any Number descendants like Integer and Double. In Java parent type can hold any descendant type.
Also use integral type int in getter argument.
Number get(int index)
Also you can use predefined class like Vector<Number> with required functionality.
public Vector<Number> myfunction() {
Vector<Number> ans = new Vector<Number>();
ans.add(new Integer(1));
ans.add(new Double(3.14));
return ans;
}

Categories

Resources