SparseBooleanArray.equals() not working as expected - java

In the following code I would expect equals() to return true, but it does not. What am I missing here?
SparseBooleanArray array_0 = new SparseBooleanArray();
array_0.put(0, true);
array_0.put(2, true);
SparseBooleanArray array_1 = new SparseBooleanArray();
array_1.put(0, true);
array_1.put(2, true);
boolean isEqual = array_0.equals(array_1); // is false instead of true
Looking at both array in the debugger, they seem the same to me (they have a different shadow$_monitor_ value, but I have no idea what that is supposed to be). The toString() method returns the same string for both as well.
I am trying to write a unit test for a function that converts an EnumSet to a SparseBooleanArray, but I can't create the same array manually to compare it with the function's return value.
Edit
I should also mention that hasCode() returns different values as well, which should not, based on the documentation.

Looking at the source code both the equals and hashCode methods are not implemented for SparseBooleanArray, SparseIntArray, SparseLongArray and SparseArray. I would say this is a critical missing feature and should be reported to Google.
Anyway, I use for quite some time these utility methods to solve this problem:
public static boolean equals(SparseArray arrayOne, SparseArray arrayTwo){
if(arrayOne == arrayTwo){
return true;
} else if(arrayOne.size() != arrayTwo.size()){
return false;
}
for(int i = 0; i < arrayOne.size(); i++){
if(arrayOne.keyAt(i) != arrayTwo.keyAt(i)){
return false;
}
final Object valueOne = arrayOne.valueAt(i);
final Object valueTwo = arrayTwo.valueAt(i);
if(valueOne != null && !valueOne.equals(valueTwo)){
return false;
} else if(valueTwo != null && !valueTwo.equals(valueOne)){
return false;
}
}
return true;
}
public static boolean equals(SparseBooleanArray arrayOne, SparseBooleanArray arrayTwo){
if(arrayOne == arrayTwo){
return true;
} else if(arrayOne.size() != arrayTwo.size()){
return false;
}
for(int i = 0; i < arrayOne.size(); i++){
if(arrayOne.keyAt(i) != arrayTwo.keyAt(i)){
return false;
} else if(arrayOne.valueAt(i) != arrayTwo.valueAt(i)){
return false;
}
}
return true;
}
public static boolean equals(SparseIntArray arrayOne, SparseIntArray arrayTwo){
if(arrayOne == arrayTwo){
return true;
} else if(arrayOne.size() != arrayTwo.size()){
return false;
}
for(int i = 0; i < arrayOne.size(); i++){
if(arrayOne.keyAt(i) != arrayTwo.keyAt(i)){
return false;
} else if(arrayOne.valueAt(i) != arrayTwo.valueAt(i)){
return false;
}
}
return true;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public static boolean equals(SparseLongArray arrayOne, SparseLongArray arrayTwo){
if(arrayOne == arrayTwo){
return true;
} else if(arrayOne.size() != arrayTwo.size()){
return false;
}
for(int i = 0; i < arrayOne.size(); i++){
if(arrayOne.keyAt(i) != arrayTwo.keyAt(i)){
return false;
} else if(arrayOne.valueAt(i) != arrayTwo.valueAt(i)){
return false;
}
}
return true;
}
It is however also possible (as mentioned in the comments), and possibly better, to subclass the SparseArray class and override the equals and hashCode methods.
Disclaimer: I did not test the hashCode or equals implementation of the code provided below, please write some tests yourself to make sure it works correctly. #DontTrustTheInternet
public class SparseBooleanArray extends android.util.SparseBooleanArray {
#Override
public boolean equals(Object o) {
if(!(o instanceof SparseBooleanArray)){
return false;
} else if(this == o){
return true;
}
final SparseBooleanArray other = (SparseBooleanArray) o;
if(size() != other.size()){
return false;
}
for(int i = 0; i < size(); i++){
if(keyAt(i) != other.keyAt(i)){
return false;
} else if(valueAt(i) != other.valueAt(i)){
return false;
}
}
return true;
}
#Override
public int hashCode() {
int result = 17;
for(int i = 0; i < size(); i++){
result = 31 * result + keyAt(i);
result = 31 * result + (valueAt(i)?1:0);
}
return result;
}
}

Related

Find array if it is subset of another array

This function should return true only if the parameter object is a subset of the calling object but it always returns true. How to fix it?
public boolean contains(FileCollection other) {
int i = 0;
int j = 0;
for (i = 0; i<other.files.length; i++) {
for (j = 0; j<this.files.length; j++) {
if ((other.files[i]).equals((this.files[j]))) //this refers to the equals method defined in File class
break;
}
if (j==this.files.length)
return false;
}
return true;//this method is in FileCollection class
}
(Since you didn't explicitly express what the data type of the array elements is, I'll assume it's File, inferred from comments.)
If you don't mind converting between data structures, maybe converting your arrays (temporarily) to Collections is the most simple way. For example, converting to List:
/* #param other
* #return true if the calling object contains
* all files in the parameter object, false otherwise
*/
public boolean contains(FileCollection other) {
List<File> myList = Arrays.asList(this.files);
List<File> otherList = Arrays.asList(other.files);
return myList.containsAll(otherList);
}
Based on your clarify of what to be considered as "contains" when duplicated items are allowed, I'd say you need to count the number of existence for each element. Here is how:
Based on the answer of #Eritrean , you can get and store the count to a map. I made modifications to check the count too:
public boolean contains(FileCollection other) {
Map<File,Integer> otherFrequency = Arrays.stream(other.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
Map<File,Integer> thisFrequency = Arrays.stream(this.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
if (thisFrequency.entrySet().containsAll(otherFrequency).entrySet()) {
for (File entry : otherFrequency.entrySet()) {
if (thisFrequency.get(entry) < otherFrequency.get(entry))
return false;
}
return true;
}
return false;
}
For other.files contains this.files to hold, every this.file must be in other.files.
for (int j = 0; j < this.files.length; j++) {
boolean found = false;
for (int i = 0; i < other.files.length; i++) {
if (other.files[i].equals(this.files[j])) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
Not knowing the class of files, probably you can do:
for (String file : this.files) {
boolean found = false;
for (String otherFile : other.files) {
if (otherFile.equals(file)) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
Or even
for (String file : this.files) {
boolean found = other.files.indexOf(file) != -1;
if (!found) {
return false;
}
}
return true;
There are nicer datastructures that speed things up, and have predefined methods for things like contains.
With duplicates
Comparator<File> comparator = new Comparator<File>() {
#Override
public int compare(File lhs, File rhs) {
int cmp = lhs.getBase().compareIgnoreCase(rhs.getBase());
if (cmp == 0) {
cmp = lhs.getExtension().compareIgnoreCase(rhs.getExtension());
}
if (cmp == 0) {
cmp = Long.compare(lhs.getSize(), rhs.getSize());
}
return cmp;
}
};
Arrays.sort(this.files, comparator);
Arrays.sort(other.files, comparator);
int otherI = 0;
for (File file : this.files.length) {
boolean found = false;
while (otherI < other.files.length) {
int comparison = comparator.compare(other.files[otherI], file);
++otherI;
if (comparison >= 0) {
found = comparison == 0;
break;
}
}
if (!found) {
return false;
}
}
return true;
By sorting both arrays you can synchronize the comparison at locations in both arrays. The above handles duplicates.
Apart from the #renyuneyun suggestion to convert your arrays into Lists you could also make use of the String contains method
public boolean contains(FileCollection other) {
String myList = Arrays.toString(this.files);
String otherList = Arrays.toString(other.files);
return myList.contains(otherList);
}
Of course both of these suggestions are not the optimum solutions from the complexity point of view, but are for sure the shortests :)
What about using a map with File as key and frequency as value:
public boolean contains(FileCollection other) {
Map<File,Integer> otherFrequency = Arrays.stream(other.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
Map<File,Integer> thisFrequency = Arrays.stream(this.files)
.collect(Collectors.toMap(Function.identity(), v->1,Integer::sum));
return thisFrequency.entrySet().containsAll(otherFrequency.entrySet());
}
Only this answer works for me: (Credit to #Joop Eggen for the Comparator part)
public boolean contains(FileCollection other) {
Comparator<File> comparator = new Comparator<File>() {
#Override
public int compare(File lhs, File rhs) {
int cmp = lhs.getBase().compareToIgnoreCase(rhs.getBase());
if (cmp == 0) {
cmp = lhs.getExtension().compareToIgnoreCase(rhs.getExtension());
}
if (cmp == 0) {
cmp = Long.compare(lhs.getSize(), rhs.getSize());
}
if (cmp == 0) {
cmp = Long.compare(lhs.getPermissions(), rhs.getPermissions());
}
return cmp;
}
};
Arrays.sort(this.files, comparator);
Arrays.sort(other.files, comparator); //THIS AND THE COMPARATOR SORT THE ARRAYS BASED ON ALL FILE ATTRIBUTES
int i = 0;
int j = 0;
if (this.files.length<other.files.length)
return false;
while (i<other.files.length && j<this.files.length) {
if (!(this.files[j].equals(other.files[i])))
j++;
else {
j++;
i++;
}
}
if (i<other.files.length)
return false;
else
return true;
}

Having trouble with detection of whether this is a BST or not

Trying to run a recursive algorithm to find out if a certain tree is a BST(Binary search tree).
boolean checkBST(Node root) {
boolean isBST = true;
if(root == null){
return false;
}
if(root.left != null){
if( isLessThan(root.data, root.left.data) == false ) {
isBST = false;
return isBST;
} else
checkBST(root.left);
}
if(root.right != null){
if(isGreaterThan(root.data, root.right.data) == false) {
isBST = false;
return isBST;
} else
checkBST(root.right);
}
return isBST;
}
boolean isLessThan(int value1, int value2){
if(value2< value1){
return true;
}
return false;
}
boolean isGreaterThan(int value1, int value2){
if(value1 < value2){
return true;
} else
return false;
}
I'm not sure whats wrong with my algorithm. Any help?
The problem is that your implementation ignores return values of recursive invocations of the method:
checkBST(root.left);
...
checkBST(root.right);
Regardless of the return value, your code continues on. Instead, it should check the return value, and return false if the check of a subtree returned false:
if (!checkBST(root.left)) {
return false;
}
...
if (!checkBST(root.right)) {
return false;
}

Java Program: return statements not working

This program creates various methods for a class and runs each method. When I run the methods, the return statements do not work in the methods, although the integer value entered is definitely passed to the object (I tested with a print statement). I am sure the issue is somewhere with my static declarations.
can anyone help?
import java.util.Scanner;
public class MyInteger {
public static int storedValue;
public int value;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("Class with various methods test. Please enter an integer:");
int num = input.nextInt();
MyInteger x = new MyInteger(num);
storedValue = x.value;
System.out.println("Now performing returnInt");
x.returnInt();
System.out.println("Now performing isEven");
x.isEven();
}
MyInteger(int a){
value = a;
}
public int returnInt(){
return storedValue;
}
public boolean isEven(){
if(value % 2 == 0){
return true;
}
else{
return false;
}
}
public boolean isOdd(){
if(value % 2 != 0){
return true;
}
else{
return false;
}
}
public boolean isPrime(){
if (value == 2){
return true;
}
for (int i = 2; i < value;i++){
if (value % i == 0){
return false;
}
}
return true;
}
public boolean isEven(int a){
if (a % 2 == 0){
return true;
}
else{
return false;
}
}
public boolean isOdd(int a){
if (a % 2 != 0){
return true;
}
else{
return false;
}
}
public boolean isPrime(int a){
if (a == 2){
return true;
}
for (int i = 2; i < a;i++){
if (a % i == 0){
return false;
}
}
return true;
}
public boolean isEven(MyInteger a){
if (a.value % 2 == 0){
return true;
}
else{
return false;
}
}
public boolean isOdd(MyInteger a){
if (a.value % 2 != 0){
return true;
}
else{
return false;
}
}
public boolean isPrime(MyInteger a){
if (a.value == 2){
return true;
}
for (int i = 2; i < a.value;i++){
if (a.value % i == 0){
return false;
}
}
return true;
}
public boolean equals(int a){
if (value == a){
return true;
}
else{
return false;
}
}
public boolean equals(MyInteger a){
if (value == a.value){
return true;
}
else{
return false;
}
}
public int parseInt(String s, int radix){
for (int i = (s.length()-1); i >= 0; i--){
radix += (int)s.charAt(i)*(Math.pow(10, i));
}
return radix;
}
}
First, remove the static storedvalue.
// public static int storedValue;
Then change your returnInt to return the value. Like,
public int returnInt(){
return value;
}
Finally, assign the return(ed) value in your caller (main, or use it directly). Something like
System.out.println("Now performing returnInt");
int v = x.returnInt();
System.out.printf("Value = %d%n", v);
System.out.println("Now performing isEven");
if (x.isEven()) {
System.out.println("It's even");
} else {
System.out.println("It's odd");
}

How do I make this output a boolean?

So here's my code, I want the output to be like this:
Given two numbers, is the second input a multiple of the first?
For Example:
Input:
3
6
Output:
true
public boolean multiple(int m, int n){
int i = 0;
int j = 0;
boolean check = true;
if(n%m == 0){
i++;
return check;
}
else{
j++;
return false;
}
}
When I try it I get an error, I think it's because the return statement is within the if and else statements.
The code is perfectly fine .. Error must be Somewhere else
public class Test1 {
public static void main(String[] args) {
System.out.println(multiple(3, 9));
}
public static boolean multiple(int m, int n){
int i = 0;
int j = 0;
boolean check = true;
if(n%m == 0){
i++;
return check;
}
else{
j++;
return false;
}
}
}
Output
true
here is output see IDEONE
The easiest way is to return the result of your if statement.
return n % m == 0;
I'm not sure what i/j are doing. You don't use them except to increment, but they are local to the function and get GC'd after the return. What you have now is basically this:
boolean bool = some_calculation();
if (bool == true)
{
return true;
}
else
{
return false;
}

Java : How to set the flag value in a array loop

This is my below mehod for Validation .
public boolean validateData(Bagform[] bagdata) {
boolean flag = false;
int length = bagdata.length;
if (length == 2) {
for (int i = 0; i < bagdata.length; i++) {
if (bagdata[i].getCallType() == null) {
flag = true;
}
}
}
else {
flag = true;
}
return flag;
}
In this basically i am checking that if the getCallType() is not null for any of the values in the array .
If its not null , then its a valid data , so i am setting the flag to true .
(Please see the code above )
But for me , i am getting the flag value still as false ( Even though the getCallype() is not null )
Please help me .
You're setting the flag to true if the call type is null. I suspect you want:
public boolean validateData(Bagform[] bagdata) {
boolean flag = true;
int length = bagdata.length;
if (length == 2) {
for (int i = 0; i < bagdata.length; i++) {
if (bagdata[i].getCallType() == null) {
flag = false;
}
}
}
return flag;
}
It's not clear why you're only performing this validation when there are exactly two entries in the array though. Unless that's really deliberate, I'd have written this has:
public boolean validateData(Bagform[] bagdata) {
for (Bagform form : bagdata) {
if (form.getCallType() == null) {
return false;
}
}
return true;
}

Categories

Resources