I have got this code, and I get an error incomparable types: java.lang.String and int, for this line of code
if ((this.name.String.compareTo(obj.name == 0)) && (this.age = obj.age))
The method is this:
public int compareTo(Object o)
{
int result;
AnyClass obj = (AnyClass)o;
if ((this.name.String.compareTo(obj.name == 0)) && (this.age = obj.age))
{
result = 0;
}
else if (this.name.compareTo(obj.name) > 0)
{
result = 1;
}
else
{
result = -1;
}
return result;
}
I think that position of your bracket isn't correct,
this.name.String.compareTo(obj.name == 0))
obj.name == 0 is the place where you probably compare String (name) to int (0). I guess you wanted to use compareTo on obj.name and then check if it's equal to zero.
I also think that in the second part
(this.age = obj.age)
You wanted to use == instead of =, so I think that the code you wanted to use is:
((this.name.compareTo(obj.name)==0) && (this.age == obj.age))
You can't compare a string to an integer :)
You can convert the string "001" into the integer "1"; or the integer "1" into the string "1".
See Integer.parseInt() or Integer.toString().
compareTo takes in Objec reference(a string in your case) as argument. But your code compareTo(obj.name == 0) passes in boolean which is not appropriate.
I think the code
if ((this.name.String.compareTo(obj.name == 0)) && (this.age = obj.age))
is actually supposed to read like this
if ((this.name.compareTo(obj.name) == 0) && (this.age == obj.age))
Changing where the == 0 is (and changing the second = to an ==) makes this code make sense.
There are a lot of problems with this implementation. It looks like this is an implementation of Comparable for class AnyClass which means the signature is wrong.
AnyClass should implement Comparable<AnyClass>, and the code should look like this:
#Override
public int compareTo(AnyClass other)
{
int ret = name.compareTo(other.name);
return ret != 0 ? ret : Integer.compare(age, other.age);
}
If you use Guava:
#Override
public int compareTo(AnyClass other)
{
return ComparisonChain.start().compare(name, other.name)
.compare(age, other.age).result();
}
((this.name.String.compareTo(obj.name == 0)) && (this.age = obj.age))
obj.name is a String, and 0 is an int. That's where you're getting the error
obj.name is String and you are comparing it with 0.
It is easier if you explain your intention with the code. The first error seems to be the comparison in compareTo obj.name == 0.
Try
if ((this.name.String.compareTo(obj.name) == 0) && (this.age == obj.age))
Which is what I guess you want to achieve.
Related
I'm working on an assignment for my computer science course requiring me to implement a Comparable interface.
We haven't discussed the interface at any sort of length except just being told it compares two objects and returns less than, greater than and equal to, but literally that's about it, which is frustrating.
I intend to do more research on it, but for now I am finding I'm confused as to why my implementation of the compareTo() method isn't working.
Eclipse is giving me an error that compareTo() must return an int, but if you notice, I am returning an integer value. So what might be the issue?
public int compareTo(Task taskToCompare) {
if(this.complete && taskToCompare.isComplete()) {
if(this.priority == taskToCompare.getPriority()) {
return 0;
}
else if(this.priority < taskToCompare.getPriority()){
return -1;
}
else if(this.priority > taskToCompare.getPriority()) {
return 1;
}
} else if(this.complete == true && taskToCompare.isComplete() == false) {
return -1;
} else if(this.complete == false && taskToCompare.isComplete() == true) {
return 1;
}
}
If the return type is int, you will have to return an int or throw an exception. Just exiting the method without a return will lead to a compiler error.
If you have a if-else-if condition, there may be a case where none of the blocks is called. You therefore should create an else statement with a return.
Also, the result of isComplete() and taskToCompare.getPriority() may change if you call the method multiple times. The compiler doesn't know if your logic prevents that.
For example, this is the case if complete is false and isComplete() also returns false. As before, the compiler doesn't know if your logic prevents that.
I think you want something like:
public int compareTo(Task taskToCompare) {
if(this.complete && taskToCompare.isComplete()) {
if(this.priority == taskToCompare.getPriority()) {
return 0;
}
else if(this.priority < taskToCompare.getPriority()){
return -1;
}
else{
return 1;
}
} else if(this.complete == true && taskToCompare.isComplete() == false) {
return -1;
} else if(this.complete == false && taskToCompare.isComplete() == true) {
return 1;
}else{
return 0;
}
}
What if this.complete == false and taskToCompare.isComplete() == false?
The compiler is complaining because you haven't covered every case.
more compact version:
public int compareTo(Task taskToCompare) {
int completeCompare = (this.complete == taskToCompare.complete) ? 0 : (this.complete ? 1 : -1);
if(completeCompare==0) {
return this.priority-taskToCompare.getPriority();
}
return completeCompare;
}
I am iterating over two collections and check if both collections contain
the same elements. I can't use Java 8.
edit 1 year after:
I created the method in the question to check if two Collections contain the same elements, without thinking about the fact that I am passing two Collection implementations into the method.
But Collection does not determine how elements are sorted. And I am iterating over the collections. Thus, some implementation of Collection could save elements in random order, while containing the same elements.
Both collections contain elements that are comparable and the content
is defined as equal, if all elements return a x.compareTo(y) with 0.
Two values are defined as different, if one of them is null, but not the other.
I want to find an elegant way to compare on nullity and prevent
a null check on the final compareTo().
My current implementation:
public static <T extends Comparable<T>> boolean isSame(#Nullable Collection<T> a, #Nullable Collection<T> b) {
if (a == null || b == null) {
return (a == null && b == null);
}
if (a.size() != b.size()) {
return false;
}
Iterator<T> aIt = a.iterator();
Iterator<T> bIt = b.iterator();
while (aIt.hasNext()) {
T aValue = aIt.next();
T bValue = bIt.next();
if (aValue == null || bValue == null) {
if (aValue == null ^ bValue == null) {
return false;
}
//both null, don't compare, continue looping...
} else if (aValue.compareTo(bValue) != 0) {
return false;
}
}
return true;
}
I want to continue the while loop, if both values are null, because that is
defined as equal.
But I am struggling with this part:
if (aValue == null || bValue == null) {
if (aValue == null ^ bValue == null) {
return false;
}
}
Question:
Is there a more elegant and readable way to compare on nullity, do a further compare if both are not null, return false if only one is null, and continue the loop, if both values are null?
The sequence as follows should work well:
if(aValue == null && bValue == null) continue; // both null; continue
if(aValue == null || bValue == null) return false; // any null; return false
if(aValue.compareTo(bValue) != 0) { // both non-null; compare
return false;
}
In Java8, you can build a Comparator that would replace comparison sequence at cost of creating an extra object (you will need to decide if you care about that):
Comparator<T> cmp = Comparator.nullsLast(Comparator.naturalOrder());
The compararor will take care of null comparison for you (since you assume that two nulls are equal):
while (aIt.hasNext()) {
T aValue = aIt.next();
T bValue = bIt.next();
if (cmp.compare(aValue, bValue) != 0) {
return false;
}
}
What I need is: Verify if an object exist in a List comparing some attributes.
I'm in a trouble here with Collections and Comparator. I'm trying to do the verify with this Binary Search:
Collections.binarySearch(listFuncionarioObs2, formFuncionarioObsIns, formFuncionarioObsIns.objectComparator);//Binary search of an object in a List of this Object.
With this comparator:
public int compare(FuncionarioObs func, FuncionarioObs funcToCompare) {
int testCodigo = -1;
if(null != func2.getCodigo()){
testCodigo = func.getCodigo().compareTo(funcToCompare.getCodigo());
}
int testData = func.getData().compareTo(funcToCompare.getData());
int testEvento = func.getEvento().compareTo(funcToCompare.getEvento());
int testAndamento = func.getAndamento().compareTo(funcToCompare.getAndamento());
if(testCodigo == 0 && testData == 0 && testEvento == 0 && testAndamento == 0){
return 0;
}else if(testData == 0 && testEvento == 0 && testAndamento == 0) {
return 0;
}
return -1;
}
But I'm a little bit lost, this is not working and I don't know the best way to do this. Someone can turn on a light for me?
Best regards,
Edited.
I'm sorting the List before the Binary Search with this code:
List<FuncionarioObs> listFuncionarioObsBD = funcionarioObsDAO.getFuncionarioObsById(sigla);
Collections.sort(listFuncionarioObsBD);
The comparator to the sort is:
#Override
public int compareTo(FuncionarioObs func) {
if(this.getCodigo() > func.getCodigo()){
return 1;
}else if(this.getCodigo() == func.getCodigo() ) {
return 0;
}else{
return -1;
}
}
CompareTo
Your compare wont work correctly. Right now it is only comparing the references of the objects. You will have to change this to compare the objects values:
#Override public int compareTo(Account aThat) {
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
//this optimization is usually worthwhile, and can
//always be added
if (this == aThat) return EQUAL;
//primitive numbers follow this form
if (this.fAccountNumber < aThat.fAccountNumber) return BEFORE;
if (this.fAccountNumber > aThat.fAccountNumber) return AFTER;
//booleans follow this form
if (!this.fIsNewAccount && aThat.fIsNewAccount) return BEFORE;
if (this.fIsNewAccount && !aThat.fIsNewAccount) return AFTER;
.
.
.
//all comparisons have yielded equality
//verify that compareTo is consistent with equals (optional)
assert this.equals(aThat) : "compareTo inconsistent with equals.";
return EQUAL;
}
from here
Finding the object
Now comes the next part. As CrtlAltDelete has hinted it dependends of whether your list is sorted or not.
If its sorted ascending: iterate through the objects till you either find one which compareTo returns a Zero (== success) or a One ( == fail).
For an unsorted list you will have to iterate through all objects in search for one that returns a Zero.
I have an array of a custom type that I want to sort by one of its String attributes. For some reason, the following code is producing wrong results. Could you point out where I might have made a mistake?
class PatientLNComparator implements Comparator<Patient>{
#Override
public int compare(Patient p1, Patient p2) {
String p1_LN = (p1 == null) ? null : p1.last_name;
String p2_LN = (p2 == null) ? null : p2.last_name;
if(p2_LN == null)
return -1;
else if(p1_LN == null)
return +1;
else if(p1_LN.equals(p2_LN))
return 0;
else if(p1_LN.compareTo(p2_LN) > 0)
return -1;
else
return +1;
}
}
One problem to start with - your comparator is inconsistent if you give it two patients with null names, or two null patient references. In particular:
Patient p1 = null;
Patient p2 = null;
int x = comparator.compare(p1, p2);
int y = comparator.compare(p2, p1);
The signs of x and y ought to be different - but they'll both be -1.
After that, it depends on how you want to compare the names. I would usually use
return p1_LN.compareTo(p2_LN);
if you want to sort in ascending order. Note that to sort in descending order you shouldn't just return -p1_LN.compareTo(p2_LN), as if the comparison returns the Integer.MIN_VALUE, the negation won't work. Instead you'd want to return p2_LN.compareTo(p1_LN);.
Note that if you're using this scheme, you don't need to call p1_LN.equals(p2_LN) either - that will be handled by the compareTo call.
You want patient to be ordered by alphabetical by last name, null patients and null last names up front?
class PatientLNComparator implements Comparator<Patient>{
#Override
public int compare(Patient p1, Patient p2) {
String p1_LN = (p1 == null) ? null : p1.last_name;
String p2_LN = (p2 == null) ? null : p2.last_name;
if (p1_LN == null && p2_LN == null)
return 0;
else if (p2_LN == null)
return -1;
else if(p1_LN == null)
return +1;
else
return p1_LN.compareTo(p2_LN);
}
}
To be stable, it really should order by some other fields, like first name, when last names are equal.
I'm assuming you want natural string ordering for this.
First of all, as it is, your compareTo branch is giving inversed results. Don't know if that's what you intended or not (as in you're saying p1 is greater than p2 when the p1's string is lower than p2's).
Furthermore, you can ditch the .equals branch of the if. The compareTo already handles this case.
Therefore a simple
if(p2_LN == null && p1_LN == null)
return 0;
else if(p1_LN == null)
return +1;
else if(p2_LN == null)
return -1;
else return p1_LN.compareTo(p2_LN)
would suffice.
I would use Guava's Ordering class for this:
class Patient {
// ...
public static final Function<Patient, String> GET_LAST_NAME =
new Function<Patient, String>() {
public String apply(Patient from) {
if (from == null) return null;
return from.last_name;
}
};
public static final Comparator<Patient> BY_LAST_NAME =
Ordering.natural()
.onResultOf(GET_LAST_NAME)
.nullsFirst();
}
This will resolve the issue with inconsistent comparison of nulls. It also makes it easy to add a secondary order (e.g. first name):
public static final Comparator<Patient> BY_LAST_NAME =
Ordering.natural()
.onResultOf(GET_LAST_NAME)
.compound(Ordering.natural().onResultOf(GET_FIRST_NAME))
.nullsFirst();
I want to compare two object based on 5-tuple which are:
srcAddr, dstAddr, srcPort, dstPort, protocol
here is what i have:
public class Flows implements Serializable, Comparable {
String srcAddr, dstAddr, srcPort, dstPort, protocol;
public int compareTo(Flows arg0) {
if(this.srcAddr == arg0.srcAddr &&
this.dstAddr == arg0.dstAddr &&
this.srcPort == arg0.srcPort &&
this.dstPort == arg0.dstPort &&
this.protocol == arg0.protocol)
return 0;
}
}
But it doesn't work. It says can not compare two strings.
Can anyone help me to know what is the problem?
Thanks.
The compiler / code checker is warning you that comparing String values with == is almost always a mistake.
But fixing that won't really help because your code does nothing like what a correctly implemented compareTo method should do.
A straight-forward implementation of compareTo for your Flows class would be:
public int compareTo(Flows other) {
int res = this.srcAddr.compareTo(other.srcAddr);
if (res != 0) {
return res;
}
res = this.dstAddr.compareTo(other.dstAddr);
if (res != 0) {
return res;
}
res = this.srcPort.compareTo(other.srcPort);
if (res != 0) {
return res;
}
res = this.dstPort.compareTo(other.dstPort);
if (res != 0) {
return res;
}
return this.protocol.compareTo(other.protocol);
}
That assumes the the fields are never null. If they are, then write a safeCompare(String, String) method that takes care with nulls and apply it to each field as above.
EDIT
Given that you are defining compareTo you also ought to declare equals and hashCode to be consistent with them. Otherwise certain collection methods are likely to behave incorrectly.
EDIT 2
The compiler error you mention in a comment on how to override compareTo method happens because the int compareTo(Flow flow) method actually implements the compareTo method of Comparable<Flow>. If you are going to declare Flow as implementing the raw interface type Comparable then the signature needs to be
public int compareTo(Object obj) {
Flow flow = (Flow) obj;
...
But a better solution would be to change the class declaration to:
public class Flows implements Serializable, Comparable<Flow> {
...
Try:
#Override
public int compareTo(final Flows that) {
return ComparisonChain.start().
compare(this.srcAddr, that.srcAddr).
compare(this.dstAddr, that.dstAddr).
compare(this.srcPort, that.srcPort).
compare(this.dstPort, that.dstPort).
compare(this.protocol, that.protocol).
result();
}
Requires Guava
Use string.equals() instead of ==.
You can write like this also, I have done like this in my project
public int compareTo(Flows arg0) {
int comp1, comp2, comp3, comp4;
comp1 = this.srcAddr.compareTo(arg0.srcAddr);
comp2 = this.dstAddr.compareTo(arg0.dstAddr);
comp3 = this.srcPort.compareTo(arg0.srcPort);
comp4 = this.protocol.compareTo(arg0.protocol);
if (comp1 == 0 && comp2 == 0 && comp3 == 0 && comp4 == 0) {
return 0;
} else {
if (comp1 != 0)
return comp1;
else {
if (comp2 != 0)
return comp2;
else {
if (comp3 != 0)
return comp3;
else {
if (comp4 != 0)
return comp4;
else
return 0;
}
}
}
}
}