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.
CodePudding user response:
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 usingString#charAt(index)
and compare usingString#equals(other)
.
With the latter you can bring down the search time to about 2%.
CodePudding user response:
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");
}
}
}
}
}
}