Home > Blockchain >  Arrays.equals without length of arrays
Arrays.equals without length of arrays

Time:10-04

I have two arrays with different length, but same elements. For example

A1 = {1,2,3,null,null}
A2 = {1,2,3}

Arrays.equals gives me false, because arrays have different length. Are there any method in java that will compare only elements in method? I don't want to use .toString I'm trying to make compare method in my own generic stack realization.

CodePudding user response:

No, because its a weird request. null does not mean 'not here', null means 'unknown / unset', that's why it throws exceptions when you interact with it: You're asking "hey, thing that has not been set yet, are you X", and there is no way to answer such a question.

That doesn't mean your code is wrong, just, you can stop looking for existing implementations. Weird requests generally aren't catered to by the core libraries (or any other). You also may want to change your mindset on null. Programming in java is a lot less aggravating if at all times a NullPointerException is a good thing. In other words, avoid using null as having any semantic meaning. If you ever write if (x == null || x.isEmpty()) you are doing it wrong. Instead, where-ever 'x' is coming from, it should hold, or be updated to ASAP, the empty string instead. So, if reading in external data (e.g. you marshalled some JSON into an object), do a 'clean' step that replaces all null values that have semantic meaning with an object that actually represents it, and for methods that return stuff, always return an object that represents what you are returning - only return null if you WANT to convey the notion that there is no result (i.e. that's not the same as 'an empty result', i.e. if any code acts like there was a result, you want it to crash).

In other words, I doubt you are asking the right question. But in case you are, you have two broad options.

First make null-less arrays then compare those as normal

One option is to make new arrays that have nulls stripped. Something like:

@SuppressWarnings("unchecked")
<T> T[] stripNulls(T[] in) {
  Class<?> componentType = in.getClass().getComponentType();

  return (T[]) Arrays.stream(in)
    .filter(x -> x != null)
    .toArray(len -> java.lang.reflect.Array.newInstance(componentType, len));
}

// which you can then use; you don't need generics for a compare,
// it wouldn't add anything at all.

boolean compare(Object[] a, Object[] b) {
  return Arrays.equals(stripNulls(a), stripNulls(b));
}

Just compare in place

If it's performance sensitive that's suboptimal. A better approach would involve a little more coding:

boolean compare(Object[] a, Object[] b) {
  Object ae = null, be = null;
  int ai = 0, bi = 0, al = a.length, bl = b.length;

  while (true) {
    /* set `ae` and `be` to the next non-null element */
    while (ae == null && ai < al) ae = a[ai  ];
    while (be == null && bi < bl) be = b[bi  ];

    /* Have we hit the end? */
    if (ai == al && bi == bl) return true;

    /* If one is at the end, but the other isn't... */
    if (ai == al || bi == bl) return false;

    /* check if the 2 current elements are equal */
    if (!ae.equals(be)) return false;
  }
}

CodePudding user response:

If you wish to see if 2 arrays are equal up to the length of the smaller one, you could use Arrays.mismatch:

boolean equalToSameLen = Arrays.mismatch(A1,A2) == Math.min(A1.length, A2.length);

For your input this would produce equalToSameLen is true as Arrays.mismatch(A1,A2) returns 3 which is same as the smaller array length. That is they both contain the same 3 initial values.

CodePudding user response:

Not a native Java Developer, but maybe this helps you?

boolean arraysEqual = Arrays.equals(Arrays.stream(a1).filter(n => n != null).toArray(), Arrays.stream(a2).filter(n => n != null).toArray())
  • Related