Comparison method violates its general contract - Java Error [duplicate] - java

This question already has answers here:
"Comparison method violates its general contract!"
(13 answers)
Closed 1 year ago.
I have defined a Comparator using the ordering wrapper. Could you explain why does this code throw an exception, "Comparison method violates its general contract!"? I would really appreciate it if you could tell me how to fix it.
Ordering<Foo> order = new Ordering<Foo>() {
#Override
public int compare(Foo left, Foo right) {
return getCompare(orderMap, left.getItemId(), right.getItemId());
}
};
Collections.sort(Foos, order);
getCompare :
private int getCompare(Map<Long, Integer> orderMap, Long leftId, Long rightId) {
int indexLeft = orderMap.get(leftId) == null ? -1 : orderMap.get(leftId);
int indexRight = orderMap.get(leftId) == null ? -1 : orderMap.get(rightId);
if (indexLeft < 0 || indexRight < 0) {
return 1;
}
return Integer.compare(indexLeft, indexRight);
}

This is the contract:
If `a.compare(b) is X, and b.compare(c) is X, then a.compare(c) must also be X, whether X is negative, or positive, or zero.
If a.compare(b) is X, then b.compare(a) must be -X: 0 remains 0, -1 turns to +1, etc.
a.compare(a) must be 0.
That's it. Your compare method breaks this in many, many ways. For example, your second line has a bug in it(surely that'd be orderMap.get(rightId) == null, you can clean that up using getOrDefault instead), if either index is not found or less than 0, your code always returns 1, which breaks the rule (a.compare(b), where a is not in the map, returns 1, and b.compare(a) would also return 1. It needs to return a negative number instead).
You're going to have to come up with a rule for what happens if one of these is not in the map. If your code is written with the assumption it can't happen, well, it is - throw an exception when your assumption doesn't hold so you can investigate why your assumption (that all provided left/rightIds are always in the map and always non-negative). As written, your code straight up asplodes in a nasty way if that happens - that's what exceptions are for. Explode in an easily debuggable way.
If that was the intent, you're going to have to make up some rules. For example: If a is in the map but b is not, then a is always higher than b. That means if (indexLeft < 0 && indexRight >= 0) return -1 and also if (indexLeft >= 0 && indexRight < 0) return +1;, in order to stick to the rules. That leaves the question: What if neither is in. You can either choose that there is then no way to order them (Return 0), but do know that means you can't put more than once such item in a TreeMap or TreeSet - but sorting a list, that's fine. Individually not-comparables are allowed, and they'll end up clumped together in an arbitrary order. That doesn't break the rules.

Related

Difference between IntStream.rangeClosed(x,y) and IntStream.range(x,y+1)

IntStream.range(x,y) would return a stream from x(inclusive) and y(exclusive).
IntStream.rangeClosed(x,y) would return a stream from x(inclusive) and y(inclusive).
I expected rangeClosed(x,y) to invoke range(x,y-1) or range(x,y) to invoke rangeClosed(x,y-1). But while looking at the source code for range it was like:
if (startInclusive >= endExclusive) {
return empty();
} else {
return StreamSupport.intStream(
new Streams.RangeIntSpliterator(startInclusive, endExclusive, false /*not closed*/), false);
}
The rangeClosed also had a very similar implementation rather than range(x,y+1). The only difference was that the third argument to Streams.RangeIntSpliterator was true instead of false denoting that the range is closed.
This boolean is then used to initialize int last field in Streams.RangeIntSpliterator class and the below comment is mentioned against it:
1 if the range is closed and the last element has not been traversed
Otherwise, 0 if the range is open, or is a closed range and all
elements have been traversed
Why is such an implementation necessary instead of range simply calling rangeClosed or the other way round? Is there any significant difference between calling rangeClosed(x,y) instead of range(x,y+1) ?
Even though there aren't any differences in the normal scenario, it would cause an issue when the input to the methods are min/max limits of Integer.
Assuming that rangeClosed(x,y) invokes range(x,y+1). If you are invoking rangeClosed(0, Integer.MAX_VALUE), then instead of the expected number of iterations (2147483648), the actual number of iterations would be 0, as Integer.MAX_VALUE + 1 would result in an overflow and an empty stream would be returned.
Similar overflow would cause the result to be different in case if an input is Integer.MIN_VALUE.

Is it valid to add a Null check and access the Integer value in the same line of if condition in Java [duplicate]

This question already has answers here:
Java logical operator short-circuiting
(10 answers)
Java null check on object
(5 answers)
Closed 2 years ago.
Say
class Person{
Integer height;
integer weight;
}
is it valid to check like this?
Person p = new Person();
if (p.height !=null && p.height >= 1 && p.weight >=1 ){}
It's fine, but note that this will still crash with a NullPointerException if p.weight is null. If you want clean code, consider this question:
What does height is null actually mean? Does it mean:
It is semantically equivalent to 0. (Then, why have it? Make your fields int, and set them properly).
It is unknown.
It is unset; this is a person who does not want their height publicized.
In particular, given that you are checking for >= 1, apparently you can have a null height, but also a negative height. What is the semantic difference between these two? If there is no difference, why are you allowing a cavalcade of different internal values that nevertheless all boil down to representing the same state? You're signing up for a bevy of checks everytime you interact with these variables, and a combinatorial explosion to test all this. Don't do it this way - create a single value to represent 'invalid' or 'unknown' or 'intentionally omitted' or whatever it is that you need to convey.
Usually it leads to better code if you [A] eliminate invalid state as early as possible, which in particular means that you do not need to check for invalid state (here, 0 and negative numbers appear to be intended as invalid) every time you use these variables, and [B] use a sentinel value and not null to indicate a unique state such as 'unset' or 'intentionally not shared'.
In other words:
Make height and weight private
Their setters will refuse to set (and throw IllegalArgumentException instead) if trying to set 0 or negative height or weight.
The fields are of type int
Constants exist for the various alternate states.
public class Person {
private static final int UNKNOWN = -1;
private static final int INTENTIONALLY_OMITTED = -2;
private int height, weight;
public Person() {
this.height = UNKNOWN;
this.weight = UNKNOWN;
}
public void setHeight(int height) {
if (height < 1) throw new IllegalArgumentException("Non-positive height");
this.height = height;
}
public void setHeightOmitted() {
this.height = INTENTIONALLY_OMITTED;
}
}
and so on. Now you can write code that is inherently readable; null is nebulous (you'd have to document what it means. Does it mean unset, or invalid, or intentionally omitted? What?), if (height == INTENTIONALLY_OMITTED) documents itself, that's a good thing.
Yes this is valid because Integer is the class representing int.
This is the reason why Integer can hold a null value. Comparison at p.height and p.weight is also valid.
Yes, because in case of && operation if first condition is true, then after second condition will be checked. If p.height is null then, First condition is false so, no other conditions will be checked.
You also have to add null check for p.width also.

What is the difference between compareAndExchange vs compareAndExchangeAcquire

Here is a snippet from Java library:
public final boolean compareAndExchangeAcquire(boolean expectedValue, boolean newValue) {
return (int)VALUE.compareAndExchangeAcquire(this,
(expectedValue ? 1 : 0),
(newValue ? 1 : 0)) != 0;
}
It is from AtomicBoolean class. How can a cast to int return a boolean?
My main question: What is the difference between compareAndExchange vs compareAndExchangeAcquire?
In layman terms: statements written prior to xxxAcquire and after xxxRelease is free to reorder while applying xxx.
The last part of the code you posted is != 0. With clarifying variable:
int a = (int)VALUE.compareAndExchangeAcquire(this,
(expectedValue ? 1 : 0),
(newValue ? 1 : 0));
return a != 0;
Of course the != operator returns a boolean.
As for the second part of the question:
Also, what is the difference between compareAndExchange vs compareAndExchangeAcquire?
Firstly some required reading: https://stackoverflow.com/a/16181675/3424746
From the above answer you should understand that compilers/processors can reorder loads/stores, and the restrictions that acquires and releases place on those. Compare and exchange is most likely implemented with a CAS instruction, which can be viewed as a load+store. compareAndExchangeAcquire and compareAndExchangeRelease add the release/acquire semantics to the CAS/load+stores in question. In other words you can use these to prevent certain reorderings, or allow certain reorderings.

Java unexpected type Error Required Variable Found Value

public boolean replaceEventAt(String eventStr, int position){
boolean answer = false;
if((position > 0) && (position <= events.size())){
events.get(position - 1) = eventStr;
answer = true;
}
return answer;
}
Error on fifth line where Java complains that position is a value not a variable please help
An assignment operates between what is known as an lvalue and an rvalue.
lvalue stands for left-hand-side-value.
rvalue stands for right-hand-side-value.
The rvalue can be many things, like a variable, a constant, a function call expression, etc, but the left side must be assignable, so it cannot be a constant or a function call.
In your case, your rvalue is a function invocation; that won't work. The compiler error message is saying exactly that.
If we knew what you are trying to do we could perhaps explain more, but it is unclear from the code that you posted that it is that you want to accomplish. Perhaps events is some collection, and you want to set the element at position position - 1 to eventStr, in this case you would probably want events.set( position - 1, eventStr );
Left hand side must be a variable (ie we should be able to assign a value to it ). But in your case it is performing a get operation So it is throwing an Error
As you are trying to replace using index I assume events is object of List interface.
In this case below code should work as per your requirement.
public boolean replaceEventAt(String eventStr, int position){
boolean answer = false;
if((position > 0) && (position <= events.size())){
events.set(position - 1, eventStr);
answer = true;
}
return answer;
}

Evaluation of && boolean operator

If i have the following if statement
if ( (row != -1) && (array[row][col] != 10) ) {
....
}
Where row is an int value and array is an int[][] object.
My question is, if this will throw an exception if row = -1 as the array won't have a -1 field, so out of bounds exception? Or will it stop at the first part of the if, the (row!=-1) and because that is false, it will ignore the rest?
Or to be sure it doesn't throw exception, i should separate the above if statement into two?
(Pls, don't tell me to check this out for my self :) I'm asking here 'cause i wanna ask a followup question as well ...)
It will stop safely before throwing an exception
The && is a short-circuiting boolean operator, which means that it will stop execution of the expression as soon as one part returns false (since this means that the entire expression must be false).
Note that it also guaranteed to evaluate the parts of the expression in order, so it is safe to use in situations such as these.
It will not throw an exception. However, if row is < -1 (-2 for example), then you're going to run into problems.
It will stop at the first part of the if. Java uses short circuite evaluation.
No, It wont. the compiler will not check the second expression if the first expression is false... That is why && is called "short circuit" operator...
Called a short-circuit evaluation via the && and if the row check fails, there is no point in continuing evaluation.
Most programming languages short-circuit the test when the first expression returns false for an AND test and true for an OR test. In your case, the AND test will be short-circuited and no exception will occur.
Many programming languages have short-circuit evaluation for logical operators.
In a statement such as A and B, the language will evaluate A first. If A is false, then the entire expression is false; it doesn't matter whether B is true or false.
In your case, when row is equal to -1, row != -1 will be false, and the short-circui the array expression won't be evaluated.
Also, your second question about the behavior of the array index is entirely language-dependent. In C, array[n] means *(array + n). In python, array[-1] gives you the last item in the array. In C++, you might have an array with an overloaded [] operator that accepts negative indexes as well. In Java, you'll get an ArrayIndexOutOfBoundsException.
Also, you might need something like the following (or just use a try/catch).
boolean isItSafe(int[][] a, int x, int y) {
boolean isSafe = true;
if (a == null || a.length == 0 || x >= a.length || x < 0 || y < 0 || y >= a[0].length ) {
isSafe = false;
}
return isSafe;
}

Categories

Resources