198

How do I test a string to see if it contains any of the strings from an array?

Instead of using

if (string.contains(item1) || string.contains(item2) || string.contains(item3))
user4157124
  • 2,809
  • 13
  • 27
  • 42
arowell
  • 2,271
  • 2
  • 15
  • 19
  • 5
    Are you asking if a string is **equal** to any of the strings in the array, or **contains** any of the strings from in the array? – Natix Jan 24 '12 at 18:51
  • 1
    You want to check if any string from the array is a substring of your input string? Or you want to check if your input string *equals* one of the string in the array? Can you be more precise? – Savino Sguera Jan 24 '12 at 18:53
  • 1
    contains, so that it takes a line and sees if it contains any of the words from a list (stored as an array of strings) – arowell Jan 24 '12 at 20:59

16 Answers16

259

EDIT: Here is an update using the Java 8 Streaming API. So much cleaner. Can still be combined with regular expressions too.

public static boolean stringContainsItemFromList(String inputStr, String[] items) {
    return Arrays.stream(items).anyMatch(inputStr::contains);
}

Also, if we change the input type to a List instead of an array we can use items.stream().anyMatch(inputStr::contains).

You can also use .filter(inputStr::contains).findAny() if you wish to return the matching string.

Important: the above code can be done using parallelStream() but most of the time this will actually hinder performance. See this question for more details on parallel streaming.


Original slightly dated answer:

Here is a (VERY BASIC) static method. Note that it is case sensitive on the comparison strings. A primitive way to make it case insensitive would be to call toLowerCase() or toUpperCase() on both the input and test strings.

If you need to do anything more complicated than this, I would recommend looking at the Pattern and Matcher classes and learning how to do some regular expressions. Once you understand those, you can use those classes or the String.matches() helper method.

public static boolean stringContainsItemFromList(String inputStr, String[] items)
{
    for(int i =0; i < items.length; i++)
    {
        if(inputStr.contains(items[i]))
        {
            return true;
        }
    }
    return false;
}
gnomed
  • 5,483
  • 2
  • 26
  • 28
  • 1
    How to use it with regular expression @gnomed – Praneeth Jul 12 '18 at 10:05
  • How can we make the first implementation case sensitive ? – thanos.a Nov 20 '19 at 20:11
  • The implementations are case sensitive already. I also have instructions for how to make it case insensitive in the bottom paragraphs of the answer. – gnomed Nov 20 '19 at 21:34
  • 1
    parallelStream uses a minimum batch size of 1024, it won't actually parallelise small lists. It's a footgun. – Callum Rogers Jul 30 '20 at 16:59
  • @CallumRogers true, I kind of left it in just so people think about it, but agree the vast majority of the time it will not make much difference (or actually be a detriment) compared to a non-parallel stream. Will try to call that out more in the answer. – gnomed Aug 04 '20 at 18:47
  • Still prefer the "old" answer, more supported and sufficient in most cases. – nibbana Oct 02 '20 at 10:58
  • Is there a better way if you want to check it for characters? Because I would have to convert my `char[]` to `String[]` which doesn't seem right. – Brentspine Sep 18 '22 at 20:21
  • To make it all primitve char logic you could convert the inputStr to a char[] and then implement the "contains" as a simple inner loop linear search of the `char[] inputStr` array with a primitive `==` check for each character. If you really wanted to optimize performance you could also sort and deduplicate the input str characters and search it using binary search for each character in your input `char[] items`. – gnomed Sep 18 '22 at 20:42
58
import org.apache.commons.lang.StringUtils;

String Utils

Use:

StringUtils.indexOfAny(inputString, new String[]{item1, item2, item3})

It will return the index of the string found or -1 if none is found.

ford prefect
  • 7,096
  • 11
  • 56
  • 83
renanleandrof
  • 6,699
  • 9
  • 45
  • 67
  • 9
    JFI: I hoped this implementation to iterate only once over the inputString, but I looked at the code in StringUtils, and sadly it's just doing N calls of the default indexOf. – alfonx Jul 21 '15 at 19:54
  • Maybe on commons3 the implementation is better! – renanleandrof Nov 17 '15 at 18:08
  • 3
    Nope, still just iterates over the Strings in org.apache.commons.lang3.StringUtils: for (int i = 0; i < searchStrs.length; i++) { CharSequenceUtils.indexOf(str, search, 0); .... – alfonx Nov 17 '15 at 22:45
  • This does not return the index of the string found (from the array), only the index of the position the string was found at. – Pluto Feb 27 '20 at 20:53
35

You can use String#matches method like this:

System.out.printf("Matches - [%s]%n", string.matches("^.*?(item1|item2|item3).*$"));
anubhava
  • 761,203
  • 64
  • 569
  • 643
22

If you use Java 8 or above, you can rely on the Stream API to do such thing:

public static boolean containsItemFromArray(String inputString, String[] items) {
    // Convert the array of String items as a Stream
    // For each element of the Stream call inputString.contains(element)
    // If you have any match returns true, false otherwise
    return Arrays.stream(items).anyMatch(inputString::contains);
}

Assuming that you have a big array of big String to test you could also launch the search in parallel by calling parallel(), the code would then be:

return Arrays.stream(items).parallel().anyMatch(inputString::contains); 
Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
  • One strange thing I noticed, I have two item in the String list, I found out, when i use 'parallel' it will not return the correct results. (even if it contains the value). – CharlesC May 11 '17 at 17:30
  • @Charles.C that's weird I can't reproduce on my side. – Nicolas Filotto May 11 '17 at 19:14
  • I am pretty sure parallelizing the stream would be suboptimal here unless input string was long (~ 500 chars). Instead if the array was large, It would probably be better to partitition the array and run each of those in parallel. – lifesoordinary May 08 '18 at 09:51
13

The easiest way would probably be to convert the array into a java.util.ArrayList. Once it is in an arraylist, you can easily leverage the contains method.

public static boolean bagOfWords(String str)
{
    String[] words = {"word1", "word2", "word3", "word4", "word5"};  
    return (Arrays.asList(words).contains(str));
}
JAN
  • 21,236
  • 66
  • 181
  • 318
Roy Kachouh
  • 1,855
  • 16
  • 24
2

Here is one solution :

public static boolean containsAny(String str, String[] words)
{
   boolean bResult=false; // will be set, if any of the words are found
   //String[] words = {"word1", "word2", "word3", "word4", "word5"};

   List<String> list = Arrays.asList(words);
   for (String word: list ) {
       boolean bFound = str.contains(word);
       if (bFound) {bResult=bFound; break;}
   }
   return bResult;
}
serup
  • 3,676
  • 2
  • 30
  • 34
2

Since version 3.4 Apache Common Lang 3 implement the containsAny method.

Arthur Vaïsse
  • 1,551
  • 1
  • 13
  • 26
2

Try this:

if (Arrays.stream(new String[] {item1, item2, item3}).anyMatch(inputStr::contains))
Óscar López
  • 232,561
  • 37
  • 312
  • 386
1

A more groovyesque approach would be to use inject in combination with metaClass:

I would to love to say:

String myInput="This string is FORBIDDEN"
myInput.containsAny(["FORBIDDEN","NOT_ALLOWED"]) //=>true

And the method would be:

myInput.metaClass.containsAny={List<String> notAllowedTerms->
   notAllowedTerms?.inject(false,{found,term->found || delegate.contains(term)})
}

If you need containsAny to be present for any future String variable then add the method to the class instead of the object:

String.metaClass.containsAny={notAllowedTerms->
   notAllowedTerms?.inject(false,{found,term->found || delegate.contains(term)})
}
Ivan Arrizabalaga
  • 686
  • 1
  • 7
  • 22
1

We can also do like this:

if (string.matches("^.*?((?i)item1|item2|item3).*$"))
(?i): used for case insensitive
.*? & .*$: used for checking whether it is present anywhere in between the string.
  • I believe wrapping the ends with `.*` makes the `?` and `$` redundant, as `.*` means "zero or more of any characters" (with some control char caveats) – Max Cascone Apr 08 '21 at 21:19
0

And if you are looking for case insensitive match, use pattern

Pattern pattern = Pattern.compile("\\bitem1 |item2\\b",java.util.regex.Pattern.CASE_INSENSITIVE);

Matcher matcher = pattern.matcher(input);
if (matcher.find()) { 
    ...
}
fdermishin
  • 3,519
  • 3
  • 24
  • 45
vsingh
  • 6,365
  • 3
  • 53
  • 57
0

If you are seraching for whole words you can do this that works case insensitive.

private boolean containsKeyword(String line, String[] keywords)
{
    String[] inputWords = line.split(" ");

    for (String inputWord : inputWords)
    {
        for (String keyword : keywords)
        {
            if (inputWord.equalsIgnoreCase(keyword))
            {
                return true;
            }
        }
    }

    return false;
}
thanos.a
  • 2,246
  • 3
  • 33
  • 29
0

in Kotlin

if ( arrayOf("one", "two", "three").find{ "onetw".contains(it) } != null ) {
    doStuff()
}
arowell
  • 2,271
  • 2
  • 15
  • 19
H.Step
  • 95
  • 1
  • 10
  • Not sure if adding a badly formatted answer in a different language than what had been asked for 9 years ago is appropriate. – Thomas Hirsch Sep 22 '21 at 15:32
  • @ThomasHirsch Why wouldn't it be? It's straightforward and definitely more useful today – 6rchid Aug 27 '22 at 12:05
0

In Apache common lang 3 support check contains any Strings. Try it:

import org.apache.commons.lang3.StringUtils;

...

if(StringUtils.containsAny(string, item1, item2, item3)){
   // your code
}
Pines Tran
  • 601
  • 4
  • 6
-3

The below should work for you assuming Strings is the array that you are searching within:

Arrays.binarySearch(Strings,"mykeytosearch",mysearchComparator);

where mykeytosearch is the string that you want to test for existence within the array. mysearchComparator - is a comparator that would be used to compare strings.

Refer to Arrays.binarySearch for more information.

Prahalad Deshpande
  • 4,709
  • 1
  • 20
  • 22
  • 2
    It should be noted that binarySearch works only on array that are sorted, either naturally or by the given comparator (if such is given). – Natix Jan 24 '12 at 18:49
-6
if (Arrays.asList(array).contains(string))
Garrett Hall
  • 29,524
  • 10
  • 61
  • 76