У меня есть String[] с такими значениями:

public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

Учитывая String s, есть ли хороший способ проверить, содержит ли VALUES s?

2506
Mike Sickler 15 Июл 2009 в 04:03

30 ответов

Лучший ответ
Arrays.asList(yourArray).contains(yourValue)

Предупреждение: это не работает для массивов примитивов (см. Комментарии).


Поскольку теперь можно используйте Streams.

String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);

Чтобы проверить, содержит ли массив int, double или long значение, используйте IntStream, DoubleStream или LongStream соответственно.

Примере

int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
3116
Ray Hulha 8 Окт 2018 в 12:35

Четыре разных способа проверить, содержит ли массив значение

  1. Использование List:

    public static boolean useList(String[] arr, String targetValue) {
        return Arrays.asList(arr).contains(targetValue);
    }
    
  2. Используя Set:

    public static boolean useSet(String[] arr, String targetValue) {
        Set<String> set = new HashSet<String>(Arrays.asList(arr));
        return set.contains(targetValue);
    }
    
  3. Используя простой цикл:

    public static boolean useLoop(String[] arr, String targetValue) {
        for (String s: arr) {
            if (s.equals(targetValue))
                return true;
        }
        return false;
    }
    
  4. Использование Arrays.binarySearch():

    Код ниже неверен, он указан здесь для полноты. binarySearch() можно использовать ТОЛЬКО для отсортированных массивов. Вы найдете странный результат ниже. Это лучший вариант, когда массив отсортирован.

    public static boolean binarySearch(String[] arr, String targetValue) {  
        return Arrays.binarySearch(arr, targetValue) >= 0;
    }
    

Быстрый пример:

String testValue="test";
String newValueNotInList="newValue";
String[] valueArray = { "this", "is", "java" , "test" };
Arrays.asList(valueArray).contains(testValue); // returns true
Arrays.asList(valueArray).contains(newValueNotInList); // returns false
84
Ivar 17 Июн 2020 в 07:34

Если массив не отсортирован, вам придется перебрать все и вызвать равенство для каждого.

Если массив отсортирован, вы можете выполнить двоичный поиск, он есть в Массивы.

Вообще говоря, если вы собираетесь проводить много проверок членства, вы можете хранить все в Set, а не в массиве.

72
Uri 14 Июл 2014 в 15:13

использование Spliterator предотвращает ненужное создание List

boolean found = false;  // class variable

String search = "AB";
Spliterator<String> spl = Arrays.spliterator( VALUES, 0, VALUES.length );
while( (! found) && spl.tryAdvance(o -> found = o.equals( search )) );

found == true, если search содержится в массиве


это работает для массивов примитивов

public static final int[] VALUES = new int[] {1, 2, 3, 4};
boolean found = false;  // class variable

int search = 2;
Spliterator<Integer> spl = Arrays.spliterator( VALUES, 0, VALUES.length );
…
0
Kaplan 6 Окт 2019 в 13:00
  1. Для массивов ограниченной длины используйте следующее (как указано camickr ). Это медленно для повторных проверок, особенно для более длинных массивов (линейный поиск).

     Arrays.asList(...).contains(...)
    
  2. Для повышения производительности при многократной проверке большего набора элементов.

    • Массив имеет неправильную структуру. Используйте TreeSet и добавьте к нему каждый элемент. Он сортирует элементы и имеет быстрый метод exist() (двоичный поиск).

    • Если элементы реализуют Comparable и вы хотите, чтобы TreeSet были отсортированы соответствующим образом:

      ElementClass.compareTo() метод должен быть совместим с ElementClass.equals(): см. Триады не пришли на бой? (В Java Set отсутствует элемент)

        TreeSet myElements = new TreeSet ();   // Сделайте это для каждого элемента (реализуя * Comparable *)  myElements.add (nextElement);   // * Альтернативно *, если массив принудительно предоставляется из другого кода:  myElements.addAll (Arrays.asList (myArray));  
    • В противном случае используйте свой Comparator:

        класс MyComparator реализует Comparator  {       int compareTo (ElementClass element1; ElementClass element2) {            // Ваше сравнение элементов            // Должно быть согласовано с равенством объектов       }        логическое равно (Object otherComparator) {            // Ваше равенство компараторов       }  }    // создаем TreeSet с компаратором  TreeSet myElements = новый TreeSet (новый MyComparator ());   // Сделайте это для каждого элемента (реализуя * Comparable *)  myElements.add (nextElement);  
    • Выплата: проверьте наличие какого-либо элемента:

        // Быстрый двоичный поиск по отсортированным элементам (производительность ~ log (размер)):  логическое значение containsElement = myElements.exists (someElement);  
5
Community 23 Май 2017 в 12:18

Используйте следующее (метод contains() в этом коде - ArrayUtils.in()):

ObjectUtils.java

public class ObjectUtils {
    /**
     * A null safe method to detect if two objects are equal.
     * @param object1
     * @param object2
     * @return true if either both objects are null, or equal, else returns false.
     */
    public static boolean equals(Object object1, Object object2) {
        return object1 == null ? object2 == null : object1.equals(object2);
    }
}

ArrayUtils.java

public class ArrayUtils {
    /**
     * Find the index of of an object is in given array,
     * starting from given inclusive index.
     * @param ts    Array to be searched in.
     * @param t     Object to be searched.
     * @param start The index from where the search must start.
     * @return Index of the given object in the array if it is there, else -1.
     */
    public static <T> int indexOf(final T[] ts, final T t, int start) {
        for (int i = start; i < ts.length; ++i)
            if (ObjectUtils.equals(ts[i], t))
                return i;
        return -1;
    }

    /**
     * Find the index of of an object is in given array, starting from 0;
     * @param ts Array to be searched in.
     * @param t  Object to be searched.
     * @return indexOf(ts, t, 0)
     */
    public static <T> int indexOf(final T[] ts, final T t) {
        return indexOf(ts, t, 0);
    }

    /**
     * Detect if the given object is in the given array.
     * @param ts Array to be searched in.
     * @param t  Object to be searched.
     * @return If indexOf(ts, t) is greater than -1.
     */
    public static <T> boolean in(final T[] ts, final T t) {
        return indexOf(ts, t) > -1;
    }
}

Как вы можете видеть в приведенном выше коде, существуют и другие служебные методы ObjectUtils.equals() и ArrayUtils.indexOf(), которые также использовались в других местах.

5
Abhishek Oza 1 Июн 2021 в 18:21

Вместо использования синтаксиса быстрой инициализации массива вы можете сразу же инициализировать его как List аналогичным образом, используя метод Arrays.asList, например:

public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");

Затем вы можете сделать (как указано выше):

STRINGS.contains("the string you want to find");
39
Peter Mortensen 5 Янв 2019 в 09:11

На самом деле, если вы используете HashSet , как предложил Том Хотин, вам не нужно беспокоиться о сортировке, и ваша скорость такая же, как при двоичном поиске в предварительно отсортированном массиве, возможно, даже быстрее.

Все зависит от того, как настроен ваш код, очевидно, но с того места, где я стою, порядок будет следующим:

В несортированном массиве:

  1. HashSet
  2. asList
  3. сортировка и двоичный

В отсортированном массиве:

  1. HashSet
  2. Двоичный
  3. asList

Так или иначе, HashSet для победы.

13
Peter Mortensen 5 Янв 2019 в 09:09

Если у вас есть библиотека коллекций Google, ответ Тома можно значительно упростить с помощью ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)

Это действительно устраняет много беспорядка из предложенной инициализации.

private static final Set<String> VALUES =  ImmutableSet.of("AB","BC","CD","AE");
11
jhodges 19 Сен 2012 в 14:13

Одно из возможных решений:

import java.util.Arrays;
import java.util.List;

public class ArrayContainsElement {
  public static final List<String> VALUES = Arrays.asList("AB", "BC", "CD", "AE");

  public static void main(String args[]) {

      if (VALUES.contains("AB")) {
          System.out.println("Contains");
      } else {
          System.out.println("Not contains");
      }
  }
}
10
Pang 8 Янв 2018 в 03:29

Разработчики часто делают:

Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);

Приведенный выше код работает, но нет необходимости преобразовывать список для установки первым. Преобразование списка в набор требует дополнительного времени. Это может быть очень просто:

Arrays.asList(arr).contains(targetValue);

Или

for (String s : arr) {
    if (s.equals(targetValue))
        return true;
}

return false;

Первый более читабельный, чем второй.

8
AndroidGeek 1 Июн 2021 в 20:47

В Java 8 используйте потоки.

List<String> myList =
        Arrays.asList("a1", "a2", "b1", "c2", "c1");

myList.stream()
        .filter(s -> s.startsWith("c"))
        .map(String::toUpperCase)
        .sorted()
        .forEach(System.out::println);
7
Shineed Basheer 2 Июн 2021 в 05:02

Использование простого цикла - наиболее эффективный способ сделать это.

boolean useLoop(String[] arr, String targetValue) {
    for(String s: arr){
        if(s.equals(targetValue))
            return true;
    }
    return false;
}

Предоставлено Programcreek

6
Ryan 7 Апр 2014 в 19:53

Попробуй это:

ArrayList<Integer> arrlist = new ArrayList<Integer>(8);

// use add() method to add elements in the list
arrlist.add(20);
arrlist.add(25);
arrlist.add(10);
arrlist.add(15);

boolean retval = arrlist.contains(10);
if (retval == true) {
    System.out.println("10 is contained in the list");
}
else {
    System.out.println("10 is not contained in the list");
}
4
Pang 8 Янв 2018 в 03:27

Arrays.asList () → затем вызов метода contains () всегда будет работать, но алгоритм поиска намного лучше, поскольку вам не нужно создавать легкую оболочку списка вокруг массива, что и делает Arrays.asList () .

public boolean findString(String[] strings, String desired){
   for (String str : strings){
       if (desired.equals(str)) {
           return true;
       }
   }
   return false; //if we get here… there is no desired String, return false.
}
3
TheArchon 17 Сен 2018 в 23:29

Если вы не хотите, чтобы регистр регистрировался

Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
3
Akhil babu K 21 Сен 2018 в 17:16

Проверь это

String[] VALUES = new String[]{"AB", "BC", "CD", "AE"};
String s;

for (int i = 0; i < VALUES.length; i++) {
    if (VALUES[i].equals(s)) {
        // do your stuff
    } else {
        //do your stuff
    }
}
3
Community 1 Июн 2021 в 18:50

Создайте логическое значение, изначально установленное в false. Запустите цикл, чтобы проверить каждое значение в массиве и сравнить со значением, которое вы проверяете. Если вы когда-нибудь найдете совпадение, установите для boolean значение true и остановите цикл. Затем подтвердите, что логическое значение истинно.

1
mandy1339 17 Май 2018 в 19:37

Попробуйте использовать метод проверки предикатов Java 8

Вот полный пример этого.

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Test {
    public static final List<String> VALUES =
            Arrays.asList("AA", "AB", "BC", "CD", "AE");

    public static void main(String args[]) {
        Predicate<String> containsLetterA = VALUES -> VALUES.contains("AB");
        for (String i : VALUES) {
            System.out.println(containsLetterA.test(i));
        }
    }
}

http://mytechnologyoughtt.blogspot.com/2019/10/java-8-predicate-test-method-example.html

https://github.com/VipulGulhane1/java8/blob/master/Test.java

1
Vipul Gulhane 2 Июн 2021 в 05:04

Проверить это можно двумя способами

A) Преобразуя массив в строку, а затем проверяя требуемую строку методом .contains

String a = Arrays.toString(VALUES);
System.out.println(a.contains("AB"));
System.out.println(a.contains("BC"));
System.out.println(a.contains("CD"));
System.out.println(a.contains("AE"));

Б) Это более эффективный метод

Scanner s = new Scanner(System.in);

String u = s.next();
boolean d = true;
for (int i = 0; i < VAL.length; i++) {
    if (VAL[i].equals(u) == d)
        System.out.println(VAL[i] + " " + u + VAL[i].equals(u));
}
-2
Community 1 Июн 2021 в 20:51

Краткое обновление для Java SE 9

Справочные массивы - это плохо. В этом случае нам нужен набор. Начиная с Java SE 9 у нас есть Set.of.

private static final Set<String> VALUES = Set.of(
    "AB","BC","CD","AE"
);

"Учитывая String s, есть ли хороший способ проверить, содержит ли VALUES s?"

VALUES.contains(s)

О (1).

Правильный тип , неизменяемый , O (1) и краткий . Красивый.*

Детали оригинального ответа

Просто чтобы очистить код для начала. У нас (исправлено):

public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

Это изменяемый статический объект, который FindBugs скажет вам очень непослушным. Не изменяйте статику и не позволяйте другому коду делать то же самое. Как минимум, поле должно быть закрытым:

private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

(Обратите внимание: вы можете сбросить бит new String[];.)

Справочные массивы по-прежнему плохи, и нам нужен набор:

private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
     new String[] {"AB","BC","CD","AE"}
));

(Параноики, такие как я, могли бы почувствовать себя более непринужденно, если бы это было обернуто в Collections.unmodifiableSet - тогда это могло бы даже быть обнародовано.)

(* Чтобы быть немного больше о бренде, в API коллекций предсказуемо все еще отсутствуют неизменяемые типы коллекций, а синтаксис по-прежнему слишком многословен, на мой вкус.)

387
Community 20 Июн 2020 в 09:12

Вы можете использовать ArrayUtils.contains из Apache Commons Lang

public static boolean contains(Object[] array, Object objectToFind)

Обратите внимание, что этот метод возвращает false, если переданный массив равен null.

Существуют также методы, доступные для примитивных массивов всех видов.

Примере:

String[] fieldsToInclude = { "id", "name", "location" };

if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
    // Do some stuff.
}
220
Intracer 19 Окт 2015 в 20:49

Как бы то ни было, я провел тест, сравнивая 3 предложения по скорости. Я сгенерировал случайные целые числа, преобразовал их в строку и добавил в массив. Затем я поискал максимально возможное число / строку, что было бы наихудшим сценарием для asList().contains().

При использовании массива размером 10 КБ результаты были:

Sort & Search   : 15
Binary Search   : 0
asList.contains : 0

При использовании массива 100K результаты были:

Sort & Search   : 156
Binary Search   : 0
asList.contains : 32

Таким образом, если массив создается в отсортированном порядке, двоичный поиск будет самым быстрым, иначе asList().contains будет подходящим вариантом. Если у вас много поисков, возможно, стоит отсортировать массив, чтобы вы могли использовать двоичный поиск. Все зависит от вашего приложения.

Я думаю, что это результаты, которых ожидает большинство людей. Вот тестовый код:

import java.util.*;

public class Test {
    public static void main(String args[]) {
        long start = 0;
        int size = 100000;
        String[] strings = new String[size];
        Random random = new Random();

        for (int i = 0; i < size; i++)
            strings[i] = "" + random.nextInt(size);

        start = System.currentTimeMillis();
        Arrays.sort(strings);
        System.out.println(Arrays.binarySearch(strings, "" + (size - 1)));
        System.out.println("Sort & Search : "
                + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        System.out.println(Arrays.binarySearch(strings, "" + (size - 1)));
        System.out.println("Search        : "
                + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        System.out.println(Arrays.asList(strings).contains("" + (size - 1)));
        System.out.println("Contains      : "
                + (System.currentTimeMillis() - start));
    }
}
51
Community 2 Июн 2021 в 05:01

В Java 8 вы можете создать поток и проверить, соответствуют ли какие-либо записи в потоке "s":

String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);

Или как общий метод:

public static <T> boolean arrayContains(T[] array, T value) {
    return Arrays.stream(array).anyMatch(value::equals);
}
37
assylias 13 Мар 2014 в 15:02

Для выполнения бинарный поиск значения. Если ваш массив не отсортирован, вам придется использовать функции сортировки в том же классе, чтобы отсортировать массив, а затем выполнить поиск по нему.

28
GKFX 23 Июн 2017 в 19:08

ObStupidAnswer (но я думаю, что здесь есть урок):

enum Values {
    AB, BC, CD, AE
}

try {
    Values.valueOf(s);
    return true;
} catch (IllegalArgumentException exc) {
    return false;
}
17
Tom Hawtin - tackline 15 Июл 2009 в 01:18

Используйте Array.BinarySearch(array,obj) для поиска данного объекта в массиве или нет.

Примере:

if (Array.BinarySearch(str, i) > -1)` → true --exists

False - не существует

2
Ruslan 24 Фев 2019 в 20:54

кратчайшее решение
массив VALUES может содержать дубликаты
начиная с Java 9

List.of(VALUES).contains(s);
2
Kaplan 15 Май 2021 в 09:31

Поскольку я имею дело с Java низкого уровня, использующим примитивные типы byte и byte [], лучшее, что я получил, - это bytes-java https://github.com/patrickfav/bytes-java кажется прекрасной работой

1
eigenfield 26 Фев 2020 в 08:19

Просто реализуйте это вручную:

public static <T> boolean contains(final T[] array, final T v) {
    for (final T e : array)
        if (e == v || v != null && v.equals(e))
            return true;

    return false;
}

Улучшение:

Внутри метода условие v != null постоянно. Он всегда оценивает одно и то же логическое значение во время вызова метода. Поэтому, если входные данные array большие, более эффективно оценить это условие только один раз, и мы можем использовать упрощенное / более быстрое условие внутри цикла for на основе результата. Улучшенный метод contains():

public static <T> boolean contains2(final T[] array, final T v) {
    if (v == null) {
        for (final T e : array)
            if (e == null)
                return true;
    } 
    else {
        for (final T e : array)
            if (e == v || v.equals(e))
                return true;
    }

    return false;
}
163
Peter Mortensen 5 Янв 2019 в 09:14