I've just been learning about priority queues and thought I'd try how it behaves with comparable interface.
Code Snippet:
import java.util.PriorityQueue;
class kinga implements Comparable<Double> {
double time=909.909;
double d;
public kinga(double a) {
this.d=a;
}
public int compareTo(Double d) {
return Double.compare(d, time);
}
public static void main(String arg[]) {
PriorityQueue<kinga> r=new PriorityQueue<kinga>();
r.add( new kinga(4545.45));
r.add( new kinga(45.4));
r.add( new kinga(1235.45));
System.out.println(r.poll()+" "+r.poll()+" "+r.poll());
}
}
It compiles but gives me Exception in thread "main" java.lang.ClassCastException: kinga cannot be cast to java.lang.Double.
What is wrong here. Can somebody tell me how comparable and priority queues work?
kinga should be comparable with kinga, not Double, so:
class kinga implements Comparable<kinga>
which means your compareTo method has to be changed to this:
public int compareTo(kinga o) {
return Double.compare(o.d, d);
}
class kinga implements Comparable<Double>
That doesn't make sense. Although your class will compare fine with Double, Double is unaware of that, and won't compare fine with instances of kinga, which will break the Comparable contract. And since a kinga can't compare with another kinga, you can't use a PriorityQueue<kinga>.
It should be
class Kinga implements Comparable<Kinga>
(note the upper-case, to respect the Java naming conventions), which means: Kinga instances are comparable together.
The compareTo method should be
#Override
public int compareTo(Kinga other) {
return Double.compare(this.d, other.d);
}
which means: I'm bigger than another Kinga if my d is bigger than the other Kinga's d.
PriorityQueue<kinga> will expect Comparable<kinga> in the add method. Passing a Comparable<Dobule> instead, is throwing ClassCastException
Can somebody tell me how comparable and priority queues work?
First get the difference between Comparable and Comparator interfaces.
Now for your question you can do something like below
First create a Comparator for Kinga
class comparableKinga implements Comparator<kinga> {
#Override
public int compare(kinga o1, kinga o2) {
return Double.compare(o1.getD(),o2.getD());
}
}
Then create your priority queue with this Comparator in the constructor
class kinga {
double d;
public kinga(double a) {
this.d = a;
}
public double getD() {
return this.d;
}
#Override
public String toString() {
return "kinga{" +
"d=" + d +
'}';
}
public static void main(String arg[]) {
PriorityQueue<kinga> r = new PriorityQueue<kinga>(11,new comparableKinga());
r.add(new kinga(4545.45));
r.add(new kinga(45.4));
r.add(new kinga(1235.45));
System.out.println(r.poll() + " " + r.poll() + " " + r.poll());
}
}
Output is as expected
kinga{d=45.4} kinga{d=1235.45} kinga{d=4545.45}
Related
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();
}
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);
}
I tried to override compareTo method however I see compiler uses Java.lang.Double.compareTo method instead of my compareTo.
What is wrong here and what should I fix and change so my own compareTo method will be used?
package GenerecEx;
import java.util.ArrayList;
import java.util.Collections;
public class ArraySort implements Comparable{
double val;
static ArrayList<Double> a=new ArrayList<Double>();
public static void main(String[] args) {
a.add(2.4);
a.add(8.4);
a.add(9.4);
a.add(4.4);
a.add(6.4);
sort(a);
printList(a);
}
public static void printList(ArrayList a1)
{
System.out.println(a1.toString());
}
static public void sort(ArrayList <Double> a1)
{
for (int i=0;i<a1.size();i++){
for(int j=0;j<a1.size()-i-1;j++){
if (a1.get(j).compareTo(a1.get(j+1))>0){
double temp = a1.get(j);
a1.set(j,a1.get(j+1) );
a1.set(j+1, temp);
}
}
}
}
#Override
public int compareTo(Object element)
{
if (this.val < (Double) element)
return -1;
else return 1;
}
}
Implementing the Comparable interface allows you to override the compareTo method on the implementing class. Having implemented Comparable on the ArraySort class, your compareTo method should actually be comparing objects of type ArraySort, not generic Objects cast as Double.
I'm learning Generics.I have written the following code just for practice. In this code I've created a single generic method for addition of two number and concatenation of two Strings as per values provided by the method call, it should be add the Integer or concatenate Strings.
class Kaushal28{
public <T> void add(T a, T b){
//System.out.println(a+b);
}
}
public class NewClass59 {
public static void main(String args[]){
Kaushal28 k = new Kaushal28();
k.add(5, 8);
k.add("5","8");
}
}
I'm not sure whether this can be done in a single method or not. If not then what can be the solution of this problem? Can I achieve this by use of generic class?
You can't have this as a generic method, but you can have a generic strategy:
interface Adder<T> { T add(T a, T b); }
and then specialize it for String and Integer:
class StringAdder implements Adder<String> {
#Override public String add(String a, String b) {
return a + b;
}
}
class IntegerAdder implements Adder<Integer> {
#Override public Integer add(Integer a, Integer b) {
return a + b;
}
}
You could then use this in a "single generic method" like this:
<T> void something(Adder<T> adder, T a, T b) {
System.out.println(adder.add(a, b));
}
something(new StringAdder(), "Hello", "World");
something(new IntegerAdder(), 1, 2);
or, of course:
System.out.println(new StringAdder().add("Hello", "World"));
System.out.println(new IntegerAdder().add(1, 2));
No it is not possible to have a generic method that covers every types so you will need to overload the method to support the target types, but here is a potential start that covers all Numbers and CharSequence:
class Kaushal28 {
public Number add(Number a, Number b){
return a.doubleValue() + b.doubleValue();
}
public CharSequence add(CharSequence a, CharSequence b){
StringBuilder sb = new StringBuilder(a.length() + b.length());
return sb.append(a).append(b).toString();
}
}
public class Kaushal28<T> {
public T add(T a, T b){
dynamic a1 = a;
dynamic b1 = b;
return a1+b1;
}
}
public class NewClass59
{
public static void Main(string[] args)
{
Kaushal28<int> ob =new Kaushal28<int>();
Console.WriteLine(ob.add(5,2));
Kaushal28<string> obj =new Kaushal28<string>();
Console.WriteLine(obj.add("5","2"));
}
}
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;
}