4

I have an arrayList that contains arrays. How do I check if the arrayList contains a specified array? I used .contains method and it returns false instead of expected true.

import java.util.ArrayList;
import java.util.Arrays;
public class main {
 public static void main(String[] args) {
 ArrayList<String[]> action = new ArrayList<String[]>();
 action.add(new String[]{"appple", "ball"});
 String[] items = new String[]{"appple", "ball"};
 if (action.contains(new String[]{"appple", "ball"})) {
 System.out.println("Yes");
 }
 System.out.println(action.contains(items)); // False
 }
}
asked Feb 25, 2021 at 2:54
1
  • 1
    This looks to be a bad design from the get-go. Consider creating a List<List<String>> or wrap the array in a class that uses java.util.Arrays.equals and java.util.Arrays.hashCode as its own equals and hashCode methods. Commented Feb 25, 2021 at 2:56

4 Answers 4

3

As you are creating different arrays (even if the contents are the same), contains will result false.

However, if you do this:

 List<String[]> action = new ArrayList<String[]>();
 String[] items = new String[]{"apple","ball"}; 
 action.add(items);
 if (action.contains(items)) 
 System.out.println("Yes");

This will print Yes. Also, some examples of the behaviour:

 String[] items = new String[]{"apple","ball"}; 
 action.add(items);
 String[] clone = items.clone();
 String[] mirror = items;
 action.contains(clone); // false 
 action.contains(mirror); // true
 items[0]="horse";
 System.out.println(mirror[0]); // "horse"
 System.out.println(clone[0]); // "apple"
 System.out.println(action.get(0)[0]); // "horse"
 mirror[1]="crazy";
 System.out.println(clone[1]); // "ball"
 System.out.println(action.get(0)[1]); // "crazy"
 System.out.println(items[1]); // "crazy"
 clone[1]="yolo";
 System.out.println(action.get(0)[1]); // "crazy"
 System.out.println(items[1]); // "crazy"
 System.out.println(mirror[1]); // "crazy"
 System.out.println(action.get(0).hashCode()); //2018699554
 System.out.println(items.hashCode()); //2018699554
 System.out.println(clone.hashCode()); //1311053135
 System.out.println(mirror.hashCode()); //2018699554

Custom "contains"

The issue here is that if you want to search for an specific array afterwards, you'd lose the references and searching an item wouldn't be possible, not even replicating the array with the same exact values.

As a workaround, you could implement your own contains method. Something like:

If you wish to get the index:

static int indexOfArray(List<String[]> list, String[] twin)
{ 
 for (int i=0;i<list.size();i++)
 if (Arrays.equals(list.get(i),twin))
 return i;
 return -1;
}

And then, call it like:

String[] toSearch = new String[]{"apple","ball"};
int index = indexOfArray(action, toSearch); 
if (index>0) 
 System.out.println("Array found at index "+index);
else
 System.out.println("Array not found");

If the index is bigger than -1, you can get your original array by just:

String[] myArray = action.get(index);

HashMap + identifier

An alternative would be storing the arrays into a HashMap by declaring an identifier for each array. For example:

Base64 ID

This will give the same result for the same values, as the encoded value is based on the entries, not the Object's reference.

 static String getIdentifier(String[] array)
 {
 String all="";
 for (String s : array)
 all+=s;
 return Base64.getEncoder().encodeToString(all.getBytes());
 }

And then you could:

Map<String, String[]> arrayMap= new HashMap<>();
String[] items = new String[]{"apple","pear", "banana"}; // *[1234] 
action.add(items);
arrayMap.put(getIdentifier(items), items); // id = QUJDYWFh
//....
//Directly finding the twin will fail
String[] toSearch = new String[]{"apple","pear", "banana"}; // *[1556]
System.out.println(action.contains(toSearch)); // false
//But if we get the identifier based on the values
String arrId = getIdentifier(toSearch); // id = QUJDYWFh
System.out.println(action.contains(arrayMap.get(arrId))); //true
//arrayMap.get(arrId)-> *[1234]
//.....

Name.

Choose a representative name and use it as Id

Map<String, String[]> arrayMap= new HashMap<>();
String[] items = new String[]{"apple","pear", "banana"};
action.add(items);
arrayMap.put("fruits", items);
//...
System.out.println(action.contains(arrayMap.get("fruits"))); // true 
 
answered Feb 25, 2021 at 3:15
4
  • The issue here is that if you want to search for an specific array afterwards, you'd lose the references and searching an item wouldn't be possible, not even replicating the array with the same exact values. Super strange. Where do I read more about this? Commented Feb 25, 2021 at 4:46
  • 1
    That's exactly what happens in your question. You know which the values are, you replicate the array point by point, and still tells you that it doesn't contain it. It's because your first array's hashcode is 1234 while the second one's is 1554 (simplified). Even with the same values, they're different objects. Commented Feb 25, 2021 at 4:50
  • 1
    String[] copy = items.clone() if you invoke items.equals(copy) the result is false. Why? Test it. System.out.println(copy.hashCode()); and System.out.println(items.hashCode()); Not the same hashcode, even for a clone. Commented Feb 25, 2021 at 4:54
  • 1
    @JJ123 dzone.com/articles/object-identity-and-equality-in-java Commented Feb 25, 2021 at 5:09
2

The 'contains' method compares equivalent hashCode values.

So if you make it like below*, it will pass.

public class main {
 public static void main(String[] args) {
 ArrayList<String[]> action = new ArrayList<String[]>();
 String[] items = new String[]{"appple","ball"};
 action.add(items);
 System.out.println("TO STRING");
 System.out.println("--"+action.get(0));
 System.out.println("--"+new String[]{"apple","ball"});
 System.out.println("HASHCODES");
 String[] sameValues = new String[]{"apple","ball"};
 System.out.println("--"+action.get(0).hashCode()); 
 System.out.println("--"+items.hashCode()); 
 System.out.println("--"+sameValues.hashCode()); 
 
 System.out.println("CONTAINS");
 System.out.println("--"+action.contains(items)); // *this
 System.out.println("--"+action.contains(sameValues));
 System.out.println("--"+action.contains(new String[]{"apple","ball"}));
 
 }
}

result is:

TO STRING
--[Ljava.lang.String;@7b1d7fff
--[Ljava.lang.String;@299a06ac
HASHCODES
--1243554231
--1243554231
--2548778887
CONTAINS
--true
--false
--false

Regarding the code shown when printing the array, these don't override toString(), so you get:

getClass().getName() + '@' + Integer.toHexString(hashCode())

For example:

[Ljava.lang.String;@7b1d7fff

  • [ stands for single dimension array
  • Ljava.lang.String stands for the type
  • @
  • 7b1d7fff Hex representation of the hashcode

However, if you want to compare the values, there is the following method.

public class main {
 public static void main(String[] args) {
 String[] items = new String[]{"apple","ball"};
 ArrayList<String> action = new ArrayList<>(Arrays.asList(items));
 if (action.contains("apple")) {
 System.out.println("Yes");
 }
 }
}
aran
13.5k5 gold badges49 silver badges76 bronze badges
answered Feb 25, 2021 at 3:54
0
2

You can iterate over this list and for each element, i.e. array, call Arrays.equals method to check equality of arrays until first match, or till the end of the list if none match. In this case it can return true for each element:

List<String[]> list = List.of(
 new String[]{"appple", "ball"},
 new String[]{"appple", "ball"});
String[] act = new String[]{"appple", "ball"};
System.out.println(list.stream()
 .anyMatch(arr -> Arrays.equals(arr, act))); // true

This method internally calls String#equals method for each element of the array, i.e. String, so this code also returns true:

List<String[]> list = List.of(
 new String[]{new String("appple"), new String("ball")},
 new String[]{new String("appple"), new String("ball")});
String[] act = new String[]{new String("appple"), new String("ball")};
System.out.println(list.stream()
 .anyMatch(arr -> Arrays.equals(arr, act))); // true
answered Feb 25, 2021 at 9:47
0
0

According to JavaDocs, "contains" method is using "equals" and "hashCode" methods in order to check whether an object is contained.

A leading question: Do you know what's the implementation of "equals" for arrays?

Check it and you will probably understand your code's execution result (hint: ==).

As "Hovercraft Full Of Eels" said, a better design will be using a list of some Collection which you DO understand / control it's "equals" and "hashCode" methods.

answered Feb 25, 2021 at 3:08

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.