I have created a HashMap object which stores a String as key and corresponding value as int. Now I want to have a Priority Queue which have all the String present in HashMap object with value as reference for assigning priorities. I have written the following code
public class URIQueue {
private HashMap<String,Integer> CopyQURI;
private PriorityQueue<String> QURI;
public class TComparator<String> {
public int compareTo(String s1, String s2) {
if (CopyQURI.get(s2) - CopyQURI.get(s1) >= 0) {
return 1;
} else {
return 0;
}
}
}
public URIQueue() {
CopyQURI=new HashMap<>(100);
TComparator<String> tc=new TComparator<>();
QURI=new PriorityQueue<>(100, tc); //Line x
}
}
Line x is showing error cannot infer type argument for priority queue. Please guide me what mistake I have done.
The error you are referring to states, that it cannot guess the generic type parameter which you have omitted. The reason for that is that the constructor you are using is not known. It is not known, because you second argument is not a comparator. Your comparator has to implement the java.util.Comparator interface in order to be type safe for the constructor to accept.
public class TComparator<String> implements Comparator<String> {
#Override
public int compare(String arg0, String arg1) {
// ...
}
}
Also mind, in the Comparator interface the appropriate method is called compare and not compareTo.
A general advice, I have to agree with Louis Wasserman, for two given arguments a comparator should always return the same result and not depend on the state of the application. It's just too easy not to think of some case and the application is eventually flawed.
Related
I can't seem to find exactly how to do this anywhere. I am writing a class that takes a comparator as a parameter/argument for the constructor of a class. I want to use that to order items in a list. But I'm not sure what to do with the comparator in the new class.
I have imported java.util.Comparator
In the class declaration I said "impements Comparator<T>"
I have written (Comparator<T> c) as the argument for the constructor of the class.
I have never used a comparator this way--I've used it as an inner class and that is it so I'm not sure how to make the compare method work in this class when I take the comparator in as an argument to the constructor.
The only things I've done that are the three bulleted items above. Anytime I try to do something with comparator I am taking in as an argument, I get an error message.
Here is the code for the constructor:
public class SortedList<T> implements Comparator<T>
//value, position and array are instance variables
//I am switching array to a List to deal with generics
private int position;
private Integer[] array;
public SortedList(Comparator<T> c){
this.position = 0;
this.array = new Integer[25];
}
public void sort(Integer num){
boolean valid = false;
int i = 0;
while(!valid && i < array.length-1){
if(num.compareTo(array[i] > 0)){
array[i+1] = array[i];
array[i] = num;
}else{
i++;
}
}
The error messages I have been getting are:
Cannot find symbol - method compareTo
I would like to be able to compare any two objects, not just integers, that was why I wanted to take a comparator as a parameter.
It's not clear from your question, but the only collection-ish construct in your snippet is an array of integer objects. Thus, the only sane thing to sort here is that array.
You'd need a Comparator<Integer> to sort that, not a Comparator<T>.
Once you have that, to sort that array, all you need to do is..
Arrays.sort(array, c);
Your SortedList<T> class must not implement the Comparator<T> interface, because this class is not used for comparing objects. However, it will use a given Comparator<T> instance to sort its entries. This means the classes and methods should have the following definitions:
public class SortedList<T> {
// ...
}
The class does not implement the Comparator<T> interface anymore.
private T[] array;
The array field should be of type T[] since this SortedList<T> object is used to sort/hold objects of type T, not Integer objects.
public SortedList(Comparator<T> c){
// ...
this.comparator = c;
}
That's correct. The constructor receives a Comparator<T> instance. You should store this reference to a field so you can later use it in your sort() method.
public void sort(){
// ...
}
The Integer argument on the sort() method doesn't make any sense, so delete it. Now you can use the stored Comparator<T> instance in your sort() method and call its compare() method to compare two objects from your stored array. A code fragment might look like this:
// ...
if (this.comparator.compare(this.array[i], this.array[i+1])) {
// it should be on the left
} else {
// it should be on the right
}
// ...
I don’t know how I can compare 2 comparable objects without some other variable which tells me which is larger. The question is: Create a class called Max that provides a single class method called max. max takes two arguments to objects that can be compared—that is, that implement the Java Comparable interface as shown above. It returns a reference to whichever is larger. If the two objects are equal, you should return the first. How Comparable is implemented is up to each class, and your method will be called on multiple different kinds of objects.
It gives the int compareTo (Object other) method in the interface but I’m having trouble finding a solution.
public class Max implements Comparable
{
public int compareTo(Object other)
{
}
public static Comparable max(Comparable first, Comparable second)
{
int fi = first.compareTo(second);
if(fi >0)
return first;
else if (fi<0)
return second;
return first;
}
}
java.lang.AssertionError: Class should not implement Comparable: expected [false] but found [true]
That is one of the errors. But also I need help writing the compareTo method.
I deleted my previous answer because I think, imho, you are over complicating this. Since the two arguments to max have implemented the Comparable<T> interface, all you have to do is call it as:
int ret = first.compareTo(second);
Then return first or second like you are doing based on the value of ret. That way you don't need to know anything about how it was implemented. Perhaps you could get some clarification from either your instructor or someone else who is working on this (I presume it is for an assignment).
It would be worthwhile for you to create some test classes which implement the interface. You can just make up some variable that represents size.
The keyword for your question is generics. You might want to do some research and read something about it. Take a look at the following example. I've implemented the class Max as a static class to keep it simple:
import java.time.LocalDate;
public class MyTestClass{
public static void main(String args[]) {
Integer i = 16;
Integer j = 15;
Integer m = Max.max(i, j);
System.out.println(m);
String k = "aaaa";
String n = "zzzz";
String s = Max.max(k, n);
System.out.println(s);
LocalDate d = LocalDate.now();
LocalDate e = LocalDate.now().plusDays(2);
LocalDate f = Max.max(d , e);
System.out.println(f);
}
static class Max{
public static <T extends Comparable> T max(T first, T second) {
if (first.compareTo(second) >= 0)
return first;
else
return second;
}
}
}
As you can see, there is a class Max with a single method max which accepts two objects, for example two integers, two strings or two date objects.
Since all these classes implement the comparable interface, you can use the max method for all object types. The compiler then decides during the runtime which comapreTo method to call, that is the compareTo of the class Integer, String, LocalDate or whatever.
I have a class representing a column. It has a comparator which looks something like this:
class Column
{
int xposition;
int usage;
#Override
public int compare(Object arg0, Object arg1)
{
// sort logic
}
}
I have a TreeSet of Columns. I want to sort the TreeSet first by x-position, and then at some point by usage.
What I tried is to create a superclass, such as Column2, that extends Column and has a different compare method. However that makes converting from Column to Column2 (or visa versa) very ugly. I also thought of a flag in the Column that indicates how to do the sort, but that would mean modifying all the objects in order to change the sort criteria.
Is there any better way to do this?
I would have the comparison logic in a set of external Comparators to represent the different sorting cases you have, and then create a new TreeSet when you want to change the sort:
class Column
{
int xposition;
int usage;
public static final Comparator<Column> SortByX = new Comparator<Column>() {
#Override
public int compare(Column c1, Column c2)
{
return Integer.compare(c1.xposition, c2.xposition);
}
};
public static final Comparator<Column> SortByUsage = new Comparator<Column>() {
#Override
public int compare(Column c1, Column c2)
{
return Integer.compare(c1.usage, c2.usage);
}
};
}
TreeSet<Column> cols = new TreeSet<>(Column.SortByX);
Then, to change the sort:
TreeSet<Column> updated = new TreeSet<>(Column.SortByUsage);
updated.addAll(cols);
cols = updated;
With appropriate synchronization if this is happening in a multi-threaded environment.
Whatever you do, do not change the behavior of an object's Comparator using mutable state. If you do, you could easily "lose track" of an object after it has been put into a collection like TreeSet.
Strategy pattern
What you want to achieve seems a classic use case for the Strategy pattern (e.g. Real World Example of the Strategy Pattern)
In essence, you want to package up this comparison function into something that you can put in a separate field for your column class - a plain class with that single function that implements Comparable would work. Then, your column would just delegate the call to whatever comparator is stored in that field.
This is exact use case of Guava's ComparisionChain:
Example taken from here :
public int compareTo(Foo that) {
return ComparisonChain.start()
.compare(this.xposition, that.xposition)
.compare(this.usage, that.usage)
.result();
}
Like Sean Bright answer, I'd use external Comparator and if you are working with Java 8, you can do it pretty easily:
public static final Comparator<Foobar> NAME_THEN_AGE =
Comparators.comparing(Foobar::getName, String.CASE_INSENSITIVE_ORDER)
.thenComparing(Foobar::getAge)
;
....
TreeSet<Foobar> foobar = new TreeSet<>(NAME_THEN_AGE);
However, better remaindered that not, it is generally a bad idea to override Comparable on a child class - perhaps it should be final on the parent or one should create a protected compareTo0(A) doing the common work (to avoid comparing object by their parent class).
There are reason for that, and one such is the following (from the Javadoc of Comparable.compareTo):
The implementor must ensure sgn(x.compareTo(y)) ==
-sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an
exception.)
Let's say you have class B and C extending A and A implements Comparable<A>:
class A implements Comparable<A> {
#Override
public int compareTo(A other) {return ...;}
}
class B extends A {
#Override
public int compareTo(A other) {return compareToAsB(((B)other));}
}
class C extends A {
#Override
public int compareTo(A other) {return compareToAsC(((C)other));}
}
It does not really matter what A::compareTo returns. Neither what compareToAsB and compareToAsC does.
The problem is however here:
A a = ...;
B b = ...;
C c = ...;
a.compareTo(b); // ok
a.compareTo(c); // ok
b.compareTo(a); // ko ClassCastException
b.compareTo(c); // ko ClassCastException
c.compareTo(a); // ko ClassCastException
c.compareTo(b); // ko ClassCastException
As quoted in the javadoc, a.compareTo(b) should throw a ClassCastException.
Also, there are part in the Java code (Collections.sort) where it is important to ensure that sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.
Numbers a,b;
a = new NumbersType(1);
b = new NumbersType(1);
System.out.println(a.equals(b));
public class NumbersType implements Numbers {
int intType;
public NumbersType (int q) {
this.intType = q;
}
public boolean equals(Numbers n) {
return this == n;
}
}
public interface Numbers {
public boolean equals(Numbers n);
}
This prints false, despite both objects being the same thing. Changing return this == n to return this.intType == n.intType yields error "cannot find symbol: variable intType, location: variable n of type Numbers".
I'm fairly new to ADT and still making my way around it, so excuse me if this is a simple question. I'm not sure why it doesn't work, however, and why I cannot reference n.intType but I can this.intType.
intType is declared on NumbersType but n is a Numbers. So you can't necessarily compare them.
Now, one thing you could do is create a method on the interface that retrieves some value. I say 'some' value instead of 'the' value because the other Numbers may be some other implementation. This is an important aspect of interfaces. If you have a Numbers you cannot know that it is actually a NumbersType. (You can find that out with instanceof but this would not be a good way to program an interface implementation. The interface's declaration should specify its interactions entirely.)
But first there's kind of a side issue which is that you're declaring an overload of Object#equals. You might be intending to declare an override which is a different thing. For the purpose of my answer, I am going to show an example of both and name the overload something different.
Now here's the modified interface:
public interface Numbers {
public int getIntType();
public boolean isIntTypeEqual(Numbers n);
}
Now that you can retrieve the int, you can compare them in the implementation class.
public class NumbersType
implements Numbers {
private int intType;
public NumbersType(int intType) {
this.intType = intType;
}
#Override
public int getIntType() {
return intType;
}
#Override
public boolean isIntTypeEqual(Number n) {
return intType == n.getIntType();
}
// overriding hashCode because we are overriding equals
#Override
public int hashCode() {
return intType;
}
#Override
public boolean equals(Object o) {
if(!(o instanceof Numbers))
return false;
return isIntTypeEqual((Numbers)o);
}
}
You may want to read:
Overriding equals and hashCode in Java
Overriding and Hiding Methods
If you are just learning this stuff, equals may not be a method you should be trying to implement. It is contractual and easy to get wrong.
Another complication is declaring equals in terms of interfaces: because equals must be symmetric, the implementations must override it identically. Otherwise the contract is broken.
Your class is NumbersType not Numbers, so you should type cast a and b in your equals method. This is why you cannot do n.intType
After you type cast, your equals method should compare intTypes of the objects, not direct references. This is why it will not work.
Your naming is a little bit confusing and I would suggest studying Polymorphism in general.
I am making a generic class that utilizes T as the main parameters. I need to sort some Ts, but to do that, I need to implement a generic compareTo. I've been looking all over to find out how to do this. I know how to implement something like
public class Foo implements Comparable {
private int age;
public Foo (int age) {
this.age = age;
}
public int compareTo(Foo a) {
if (age < a.age) {
return -1;
}
if (age == a.age) {
return 0;
}
if (age > a.age) {
return 1;
} else {
return 0;
}
}
}
but I'm lost when I'm trying to compare two generic objects (e.g., if T is Integer, it compares Integers, if T is String, it compares String). Basically, this:
T.compareTo(T)
I know it's probably an easy solution that I'm overlooking, but I don't understand because there is no variable I can compare.
Use the generic form of Comparable with a generic type parameter, instead of the raw form of Comparable that has none. It makes sense to compare Foo objects with other Foo objects. I wouldn't use a generic type parameter; I would just supply Foo as the type parameter on Comparable.
Try
public class Foo implements Comparable<Foo> {
Then your compareTo method should work.
If you want your class to be able to sort things of some arbitrary type T, you have two options, and you can do them both at once if you like.
public class Sorter {
public static < T extends Comparable< ? super T > >
void sort( T[] atUnsorted ) {
// here you know that the elements of atUnsorted
// can be compared with each other using their
// compareTo methods
...
}
public static < T > void sort(
T[] atUnsorted, Comparator< ? super T > cmpT
) {
// here you can use cmpT.compare to compare
// any two elements in atUnsorted
...
}
}
If you prefer having a dedicated Sorter instance for each type T you can make the type parameter into a class level generic parameter and not use static methods.