Java Comparator multiple params - java

I'm trying to create an Comparator on my custom type.
Type {
int state = 0; // can be 0 or 1
String name = ""; // can be anything
}
I'm trying to sort the list so, that at first, on the top of list are items with one state and on the bottom the other state.
And in second step, items in both section (section 1: state 0, section 2: state 1), are sorted alphabetically.
I've tried this:
#Override
public int compare(Type i1, Type i2) {
boolean a = i1.state == 1;
boolean b = i2.state == 1;
if (a && b) {
return i1.name.compareTo(i2.name);
} else if (a && !b) {
return 1;
} else {
return -1;
}
}
But item's get kind of randomized with each item state change.
List with these items:
name : A B C D E F G H I J K
state: 1 0 1 1 0 1 0 0 1 1 0
should be listed like this:
B 0
E 0
G 0
H 0
K 0
A 1
C 1
D 1
F 1
I 1
J 1
Have anybody an idea how to solve it?
Thanks

Your code breaks when both states are equal to zero. You could fix it by using this condition
if (a == b) ...
instead of
if (a && b)
...or try this instead:
#Override
public int compare(Type i1, Type i2) {
int res = i1.state - i2.state;
if (res == 0) {
return i1.name.compareTo(i2.name);
} else {
return res;
}
}

Why don't you implement Comparable and put the same logic in the compareTo method?

Related

TimSort violation

What's wrong with this comparator method?
I have read :
Java error: Comparison method violates its general contract
And understand that if c1 > c2, and c2 > c3, then c1 > c3. I believe this should hold true in the above.
getMaxCosine() returns value between 0..1, and 2nd sort is by the length of the text in the card, the longer the higher ranked.
public int compare(Card c1, Card c2) {
if (getMaxCosine(c1) > getMaxCosine(c2)) {
return -1;
} else if (getMaxCosine(c1) == getMaxCosine(c2)) {
return getMatchingText(c1).length() >= getMatchingText(c2).length() ? -1 : 1;
} else {
return 1;
}
}
I think your issue is in your if-else block:
else if (getMaxCosine(c1) == getMaxCosine(c2)) {
return getMatchingText(c1).length() >= getMatchingText(c2).length() ? -1 : 1;
}
If getMatchingText(c1).length() is equal to getMatchingText(c2).length() then you return -1. This yields an "unstable" sort: In other words, the order two objects with equal values will be reversed after sorting. Moreover, you should return 0 for Cards that are equal under this comparator. I suggest changing the >= comparison to just > in this if-else block:
else if (getMaxCosine(c1) == getMaxCosine(c2)) {
if (getMatchingText(c1).length() == getMatchingText(c2).length()) return 0;
return getMatchingText(c1).length() > getMatchingText(c2).length() ? -1 : 1;
}

compare three different values and return true false accordingly? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have a below code which takes three input parameters a, b and c and compare three different values and basis on that it returns true false..
public boolean compare(int a, int b, int c) {
int value = increment(a, c);
if (a < value && b < c || a < value && b > c && c < b) {
return true;
}
return false;
}
private int increment(int a, int c) {
int f = 0;
for (int i = 0; i < c; i++) {
f += a;
}
return f;
}
Any better way to write this?
You have an undefined method u in your code. Assuming u is a misspelling of increment, then this is the simplest you can get:
public boolean compare(int a, int b, int c) {
return c > 1 && b != c;
}
Your increment function returns the product of the two numbers (which means it has the wrong name). If value is increment(a, c), then value is a * c. If you compare a < a * c and are given that a and c are greater than 0, then since a*c equals a if c==1 and is greater than a if c>1, then a < a * c is equivalent to testing whether c > 1.
Looking at your condition, ((a < value && b < c) || (a < value && b > c && c < b)): This returns true if either of the expressions around || is true. But a < value has to be true in both cases. So we can extract it. So for the expression to be true, a < value has to be true, and then either of the remaining parts of the expressions has to be true, so the above is equivalent to
a < value && (b < c || (b > c && c < b))
and since b > c means the same thing as c < b we can eliminate the redundancy:
a < value && (b < c || b > c)
and testing whether b is either less than or greater than c is the same as testing that they're not equal:
a < value && b != c
and as was shown above, a < value is the same as c > 1, thus
c > 1 && b != c
The only thing i can reduce is your increment(), it can be a single line expression. Also use parenthesis in if condition to make it more clear. Also b>c && c<b is same thing in two form reduce it to b>c only.
public boolean compare(int a, int b, int c) {
int value = a*c;
if (a < value && b < c || a < value && b > c) {
return true;
}
return false;
}
Maybe you can clarify what you want to do here, the code as you have laid it out is very repetitive and looks like it might have logic bugs...
As for simplification:
1) The if in compare can be greatly simplified:
if (a < value && b!=c) {
return true;
}
This is because you test for a < value on both sides of the ||, and then test for b<c on one side and c<b on the other. Thus this only fails when a>value or when b==c.
2) In increment you can just multiply your input parameters:
private int increment(int a, int c) {
return a*c;
}
You add a a number of times equal to c, which is exactly what multiplication does...

Why is Integer.MIN_VALUE failing on Balanced Binary Tree? What's the bug?

https://leetcode.com/problems/balanced-binary-tree/
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as a binary
tree in which the depth of the two subtrees of every node never differ
by more than 1.
public class Solution {
public boolean isBalanced(TreeNode root) {
int ret = getLevel(root);
if(ret < 0)
return false;
return true;
}
public int getLevel(TreeNode node) {
if(node == null)
return 0;
int l = getLevel(node.left);
int r = getLevel(node.right);
if(Math.abs(l - r) > 1)
return -99;
return Math.max(l + 1, r + 1);
}
}
This code is Accepted.
However if I replace -99 with Integer.MIN_VALUE, my code fails. What's the bug?
e.g.
Input: [1,2,null,3,null,4,null,5]
Output: true
Expected: false
Your code is failing because of integer arithmetic which is overflowing. The following code snippet will demonstrate this:
int val = Integer.MIN_VALUE;
System.out.println(val);
val -= 3;
System.out.println(val);
Output:
-2147483648
2147483645
Now consider what is happening in your actual code:
int l = getLevel(node.left);
// l == -2147483648 == Integer.MIN_VALUE assuming your base case is hit
int r = getLevel(node.right);
// assuming positive r, then Math.abs() will return a massively positive number
if (Math.abs(l - r) > 1)
return -99;
In other words, the above if statement will be firing true when it really should have fired false.
Solution:
If you modify the getLevel() method to the following, you should skirt the problems you are having:
public int getLevel(TreeNode node) {
if(node == null)
return 0;
int l = getLevel(node.left);
int r = getLevel(node.right);
if ( (l < 0 ^ r < 0) || Math.abs(l - r) > 1) {
// you can simply return -1 here, since an actual
// level should never have a negative value
return -1;
}
else {
return Math.max(l + 1, r + 1);
}
}
It may fail under some circumstances due to overflow. If l is zero and r is Integer.MIN_VALUE, l-r is actually negative because it overflows. As a result, the condition will fail and the next statement returns max of MIN_VALUE+1 and zero+1.

Using a comparator in Java

I am Having a tuple <Rank[0] , Rank[1]> and wanted to sort this in increasing order Rank[0] can be considered as first digit and Rank[2] as a second digit.
Here is my function:
Arrays.sort(S,new Comparator<Tuples>() {
public int compare(Tuples a, Tuples b) {
// TODO Auto-generated method stub
return (a.Rank[0]==b.Rank[0]) ? ((a.Rank[1]<b.Rank[1]) ? 1:0) :((a.Rank[0]<b.Rank[0])? 1:0);
}
});
The above thing is not giving be Sorted Array while it's C equivalent works i.e
int cmp(struct suffix a, struct suffix b)
{
return (a.rank[0] == b.rank[0])? (a.rank[1] < b.rank[1] ?1: 0):
(a.rank[0] < b.rank[0] ?1: 0);
}
Why My java Sorting is not working. Please Help
static class Tuples{
int[] Rank = new int[2];
}
What about something like this:
public int compare(Tuples a, Tuples b) {
int index = a.Rank[0] == b.Rank[0] ? 1: 0;
return a.Rank[index] - b.Rank[index];
}
A little easier to read in my opinion.
According to the documentation of the Comparator interface, the compare method must return 1, 0 or -1, that are:
0 = the objects are equal
-1 (or any negative integer) = the
object a is less than object b
1 (or any positive integer) = the
object a is greater than object b
So your method must be something like below:
public int compare(Tuples a, Tuples b) {
if(a.Rank[0]==b.Rank[0]){
if(a.Rank[1]==b.Rank[1]){ // a == b
return 0;
}else if(a.Rank[1]<b.Rank[1]){ // a < b
return -1;
}else{ // a > b
return 1;
}
}else{ // a != b
if(a.Rank[0]<b.Rank[0]){ // a < b
return -1;
}else{ //a > b
return 1;
}
}
}
Or in short (and ugly way) it would be like this:
public int compare(Tuples a, Tuples b) {
return (a.Rank[0]==b.Rank[0])?((a.Rank[1]==b.Rank[1])?0:((a.Rank[1]<b.Rank[1])?-1:1)):((a.Rank[0]<b.Rank[0])?-1:1);
}
As SqueezyMo stated in his answer case less and negative integer is missing. One can utilize subtraction to get compact code.
Arrays.sort(arr, new Comparator<Tuples>() {
public int compare(Tuples a, Tuples b) {
return a.Rank[0] == b.Rank[0] ? a.Rank[1] - b.Rank[1] : a.Rank[0] - b.Rank[0];
}
});
Naturally everything can be done using ternary operators, it drives maintainers crazy.
public static void main(String[] args) {
Tuples a = new Tuples();
a.Rank = new int[]{1, 2};
Tuples b = new Tuples();
b.Rank = new int[]{0, 1};
Tuples c = new Tuples();
c.Rank = new int[]{1, 3};
Tuples[] arr = {a, b, c};
Arrays.sort(arr, new Comparator<Tuples>() {
#Override
public int compare(Tuples a, Tuples b) {
return a.Rank[0] == b.Rank[0]
? a.Rank[1] == b.Rank[1]
? 0 : a.Rank[1] < b.Rank[1]
? -1 : 1 : a.Rank[0] > b.Rank[0]
? 1 : -1;
}
});
for (int i = 0; i < 3; i++) {
System.out.println(arr[i].Rank[0] + ":" + arr[i].Rank[1]);
}
}
static class Tuples {
public int[] Rank;
}

Boolean Satements

public class A4work
{
private static int fibonacci(int n) {
if (n <= 1) {
return n;
}
{
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
private static boolean isAfibonacci(int a) {
int x = 0; //sequence number
int c = 0; //number in fib sequence
while (a <= c) {
c = fibonacci(x);
x++;
}
if (a == c) {
return true;
} else {
return false;
}
}
public static void main(String[] args) //called a method signiture
{
System.out.println("The 5th Square pyramidal number is " + isAfibonacci(3));
}
}
I think I have the code right, but it keeps on returning false. I'm using it to decide if a number is in the fib sequence or not.
Thanks for the help
When you use System.out.println("The 5th Square pyramidal number is "+ isAfibonacci(3) );, a in your isAfibonacci(); method becomes 3. Now look at your code knowing that.
while(3 <= 0) //replaced a with 3 here and c with 0 for visualization
{
...
}
A non-negative, non-zero integer will never be less than or equal to 0, therefore, will always result in false.
If your input a is 5, for example, you will have:
int c = 0; //number in fib sequence
while (a <= c) { ... }
The while loop will never run since 5 <= 0 is false. So a == c will always be false for any a greater than zero.
I think you want to stop iterating when c is greater than or equal to a, so the correct condition would be
while (c < a) { ... }

Categories

Resources