3

I have an array of arrays - similar to this:

import java.util.Arrays;

public class test {
    public static void main(String[] args)
    {

        String[][] A = { { "a", "b", "c" }, { "d", "e", "f" }, { "g", "h", "-" } };
        String[][] B = { { "-", "e", "b" }, { "a", "h", "c" }, { "d", "g", "f" } };
        String[][] C = { { "a", "b", "c" }, { "d", "e", "f" }, { "g", "h", "-" } };
        String[][][] myArray = { A, B};

        for (String[][] s : myArray) {
            System.out.println(Arrays.deepToString(s));
            if (Arrays.deepToString(s).equals(Arrays.deepToString(C))) {
                System.out.println("true");
            }
        }
    }
}

I need to check if a value is in the array, however, this is the only method I have found to work and it is very inefficient.

Is there a better way to do this since most built-in methods do not appear to work?

I also tried to use a Set and that had the same issues.

0

2 Answers 2

2

This is easy: never convert to strings. Try deepEquals it should do what you want, although you of course first have to dive into your myArray and iterate over the elements.

public static boolean contains(String[][][] set, String[][] obj) {
    for (String[][] elt : set) {
        if (Arrays.deepEquals(elt, obj)) {
            return true;
        }
    }
    return false;
}

This performs the contains function for your test set in about 4.5% of the time.


Java has type erasure when it comes to arrays over objects (including other arrays). As such it may be slightly faster to create deepEquals(String[][], String[][]) yourself where you use Arrays.equals(String[], String[]), as you would not have to check if the objects are arrays of String at runtime, nor would you have to check if there are any arrays nested even deeper.

public static boolean fasterContains(String[][][] set, String[][] obj) {
    for (String[][] elt : set) {
        if (deepEquals(elt, obj)) {
            return true;
        }
    }
    return false;
}

private static boolean deepEquals(String[][] a, String[][] b) {
    int n = a.length;
    if (b.length != n) {
        return false;
      }
      
     for (int i = 0; i < n; i++) {
        if (!Arrays.equals(a[i], b[i])) {
            return false;
        }
    }
    return true;
}

This performs the contains function for your test set in about 3.5% of the time, while being only slightly more complex than the test above.


As a general hint: computers are not efficient when it comes to Strings (although newer Java versions did address this somewhat). Anyway, never convert to string for any comparison, calculation, concatenation or whatnot. Always compare bytes, integers or objects (i.e. the original data) unless there is really no other way.


If you just have a list of characters then there are two observations:

  • char[][] should also work;
  • or just a String[] of course, where the String consist of the various characters (which you can retrieve using String#charAt(index) and compare using String#equals(other).

With the latter you can bring down the search time to about 2%.

Sign up to request clarification or add additional context in comments.

Comments

1

Another way would be to store/hash your arrays as StringBuilder and compare it with the StringBuilder formed in the multidimentional array.

StringBuilder is faster for String operations compared to String. Here is the code:

import java.util.Arrays;

public class test {
    public static void main(String[] args)
    {

        String[][] A = { { "a", "b", "c" }, { "d", "e", "f" }, { "g", "h", "-" } };
        String[][] B = { { "-", "e", "b" }, { "a", "h", "c" }, { "d", "g", "f" } };
        String[][] C = { { "a", "b", "c" }, { "d", "e", "f" }, { "g", "h", "-" } };
        String[][][] myArray = { A, B};
        StringBuilder str = new StringBuilder();
        StringBuilder str1 = new StringBuilder();
        for(String[] ss : C){
            for(String s : ss){
                for(char p : s.toCharArray()){
                            str1.append(p);
                        }
            }
        }
        String cc = str1.toString();
        for(String[][] s : myArray){
            for(String[] ss : s){
                for(String sss : ss){
                    for(char p : sss.toCharArray()){
                        str.append(p);
                    }
                    if(str.toString().equals(cc)){
                        System.out.println("true");
                    }
                }
            }
        }
        
    }
}

1 Comment

OK, but it still only runs at 60% time. It's certainly a speedup, but nothing near the 20-50 times speedup that you can achieve by simply not converting to string. In the end, it is still a stringified solution with a lot of unnecessary complexity. Still, voted up since faster is faster.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.