athena
athena

Reputation: 5709

Checking containment in a Set of strings in Java

I have a Set of String[]. I want to check whether this Set contains another String[].

Set<String[]> s  = new HashSet<String[]>();
s.add(new String[] {"lucy", "simon"});
System.out.println(s.contains(new String[] {"lucy", "simon"}));

However, false is printed. My guess is this is because only the references are being compared and not the actual Strings. It seems, the only option I have is to create a class, say Phrase, and implement hashCode() and equals() (that use Arrays.hashCode(...)).

Is there any other way to achieve what I want?

Upvotes: 9

Views: 25575

Answers (7)

Johnny
Johnny

Reputation: 15413

With Java8 stream introduction you can do it the following way:

Boolean res = s.stream()
  .anyMatch(elm -> elm.equals("lucy") || elm.equals("simon"));

Upvotes: 0

haylem
haylem

Reputation: 22663

Can the elements of the String[] be in different orders and still make the whole array be considered equal to another array containing the same elements in another order? If yes, you'd indeed be better off implementing a container class and overriding equals and hashcode.

if not, and if storing the internal elements as Lists instead of arrays is an acceptable alternative, then you could do this:

package com.stackoverflow;


import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


public class StringContainment {

  public static void main(final String[] args) {
    final Set<String[]> s = new HashSet<String[]>();
    final Set<List<String>> s2 = new HashSet<List<String>>();

    s.add(new String[] {"lucy", "simon"});
    s2.add(Arrays.asList(new String[] { "lucy", "simon" }));

    System.out.println(s.contains(new String[] {"lucy", "simon"})); // false
    System.out.println(s2.contains(Arrays.asList(new String[] {"lucy", "simon"}))); // true
  }

}

The first check will return false, the second true. Might be easier that way if you can use lists.

If you can't, you could still use this as long as you don't need to do this comparison too often (it's definitely not a good idea performance-wise).

Upvotes: 3

Emil
Emil

Reputation: 13789

Use Set<Set<String>> or Set<List<String>> instead of Set<String[]>

Code:

List<String> s1=Arrays.asList("1","2"),s2=Arrays.asList("1","2");
System.out.println(s1.equals(s2) + " "+s1.hashCode()+ " "+s2.hashCode());

Output:

true 2530 2530

Upvotes: 1

laher
laher

Reputation: 9110

I'd just loop through and call Arrays.equals:

something like this:

boolean contains(Set<String[]> s, String[] item) {
  for(String[] toCompare: s) {
    if(Arrays.equals(toCompare, item)) {
        return true;
    }
  }
  return false;
}

not sure if it's the fastest but it should do the job nicely

Upvotes: 0

Przemek Kryger
Przemek Kryger

Reputation: 687

Sounds like you've already answered your question. One option is as you already stated. The another would be to use Set>, since the API for equals(Object) says:

Compares the specified object with this collection for equality.

Upvotes: 1

Ralph
Ralph

Reputation: 120811

Your guess is correct: arrays ([]) do not implement a deep equals method: they are equals if they are the same instance.

The simplest solution would be: replacing String[] by List<String>

An other way (but i do not recommend it) is to implement your own Set, which does not based on Object.equals but on java.util.Arrays.equals(Object[]a, Object[]b)

Upvotes: 13

Sanjay T. Sharma
Sanjay T. Sharma

Reputation: 23208

Convert that String[] to List<String> and it should work out pretty well.

Set<List<String>> s  = new HashSet<List<String>>();
s.add(Arrays.asList("lucy", "simon"));
System.out.println(s.contains(Arrays.asList("lucy", "simon")));

Upvotes: 12

Related Questions