Check if two Bundle objects are equal in Android?

2020-08-20 15:50发布

问题:

I would like to check if two bundles are equal, is there any way to do that instead of checking them key by key?

回答1:

Here is one way to test if two Bundles are the same:

  • Check their sizes, don't bother if they're not equal
  • If both values are Bundle objects use recursion
  • Because a value for a key in one can be null, make sure that both values are null and that the key actually exists in two
  • Finally compare the matching keys' values

Code:

public boolean equalBundles(Bundle one, Bundle two) {
    if(one.size() != two.size())
        return false;

    Set<String> setOne = new HashSet<>(one.keySet());
    setOne.addAll(two.keySet());
    Object valueOne;
    Object valueTwo;

    for(String key : setOne) {
        if (!one.containsKey(key) || !two.containsKey(key))
            return false;

        valueOne = one.get(key);
        valueTwo = two.get(key);
        if(valueOne instanceof Bundle && valueTwo instanceof Bundle && 
                !equalBundles((Bundle) valueOne, (Bundle) valueTwo)) {
            return false;
        }
        else if(valueOne == null) {
            if(valueTwo != null)
                return false;
        }
        else if(!valueOne.equals(valueTwo))
            return false;
    }

    return true;
}


回答2:

private static boolean equalsBundles(Bundle a, Bundle b) {
        Set<String> aks = a.keySet();
        Set<String> bks = b.keySet();

        if (!aks.containsAll(bks)) {
            return false;
        }

        for (String key : aks) {
            if (!a.get(key).equals(b.get(key))) {
                return false;
            }
        }

        return true;
    }


回答3:

I have tested Sam's answer and it contains a flaw. Plus I am loving Kotlin at the moment, so here is my version.

  • Again the keys sets need to be the same size
  • The key sets need to have the same values
  • If both values are Bundle then test recursively.
  • Otherwise test values for equality (don't retest bundles)

Code:

fun equalBundles(one: Bundle, two: Bundle): Boolean {
    if (one.size() != two.size())
        return false

    if (!one.keySet().containsAll(two.keySet()))
        return false

    for (key in one.keySet()) {
        val valueOne = one.get(key)
        val valueTwo = two.get(key)
        if (valueOne is Bundle && valueTwo is Bundle) {
            if (!equalBundles(valueOne , valueTwo)) return false
        } else if (valueOne != valueTwo) return false
    }

    return true
}


回答4:

In order to handle:

  • Bundles with bundle values
  • Bundles with lists of bundle values

I came up with this:

private static boolean equalBundles(final Bundle left, final Bundle right) {
    if (!left.keySet().containsAll(right.keySet()) || !right.keySet().containsAll(left.keySet())) {
        return false;
    }

    for (final String key : left.keySet()) {
        final Object leftValue = left.get(key);
        final Object rightValue = right.get(key);
        if (leftValue instanceof Collection && rightValue instanceof Collection) {
            final Collection leftCollection = (Collection) leftValue;
            final Collection rightCollection = (Collection) rightValue;
            if (leftCollection.size() != rightCollection.size()) {
                return false;
            }
            final Iterator leftIterator = leftCollection.iterator();
            final Iterator rightIterator = rightCollection.iterator();
            while (leftIterator.hasNext()) {
                if (!equalBundleObjects(leftIterator.next(), rightIterator.next())) {
                    return false;
                }
            }
        } else if (!equalBundleObjects(leftValue, rightValue)) {
            return false;
        }
    }
    return true;
}

private static boolean equalBundleObjects(final Object left, final Object right) {
    if (left instanceof Bundle && right instanceof Bundle) {
        return equalBundles((Bundle) left, (Bundle) right);
    } else  {
        return left == right || (left != null && left.equals(right));
    }
}