Как определить, содержит ли массив определенное значение в Java?

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

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

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

27 ответов


Arrays.asList(yourArray).contains(yourValue)

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


С java-8

теперь вы можете использовать Stream чтобы проверить, является ли массив int, double или long содержит значение (соответственно, используя IntStream, DoubleStream или LongStream)

пример

int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);

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

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

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

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

(обратите внимание, вы можете на самом деле бросить


можно использовать 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.
}

Я удивлен, что никто не предложил просто реализовать его по руке:

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;
}

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

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

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


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

1) Использование Списка:

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) Использование Массивов.binarySearch ():

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

public static boolean binarySearch(String[] arr, String targetValue) {  
            int a = Arrays.binarySearch(arr, targetValue);
            return a > 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

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

при использовании размера массива 10K результаты где:

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));
    }
}

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

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

тогда вы можете сделать (как указано выше):STRINGS.contains("the string you want to find");


С 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);
}

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


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

enum Values {
    AB, BC, CD, AE
}

try {
    Values.valueOf(s);
    return true;
} catch (IllegalArgumentException exc) {
    return false;
}

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

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

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

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

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

  1. поиска HashSet
  2. Бинарные
  3. asList

Так или иначе, HashSet ftw


Если у вас есть библиотека Google collections, ответ Тома можно упростить, используя 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");

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

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");
      }
  }
}

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

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;

первый является более читаемым, чем второй.


на 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);

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

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

вежливость Programcreek


  1. для массивов ограниченной длины используйте следующее (Как указано camickr). Это медленно для повторных проверок, особенно для более длинных массивов (линейный поиск).

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

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

    • если элементы реализации Comparable и вы хотите, чтобы TreeSet отсортированный образом:

      ElementClass.compareTo() метод должен быть совместим с ElementClass.equals(): см.триады не появляются, чтобы сражаться? (Java Set отсутствует элемент)

      TreeSet myElements = new TreeSet();
      
      // Do this for each element (implementing *Comparable*)
      myElements.add(nextElement);
      
      // *Alternatively*, if an array is forceably provided from other code:
      myElements.addAll(Arrays.asList(myArray));
      
    • в противном случае, используйте свой собственный Comparator:

      class MyComparator implements Comparator<ElementClass> {
           int compareTo(ElementClass element1; ElementClass element2) {
                // Your comparison of elements
                // Should be consistent with object equality
           }
      
           boolean equals(Object otherComparator) {
                // Your equality of comparators
           }
      }
      
      
      // construct TreeSet with the comparator
      TreeSet myElements = new TreeSet(new MyComparator());
      
      // Do this for each element (implementing *Comparable*)
      myElements.add(nextElement);
      
    • выплата: проверить существование некоторого элемента:

      // Fast binary search through sorted elements (performance ~ log(size)):
      boolean containsElement = myElements.exists(someElement);
      

массивы.asList () - > тогда вызов метода contains () всегда будет работать, но алгоритм поиска намного лучше, так как вам не нужно создавать легкую оболочку списка вокруг массива, что и является массивами.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.
}

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

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

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


Я очень поздно присоединяюсь к этому обсуждению, но поскольку мой подход к решению этой проблемы, когда я столкнулся с ней несколько лет назад, немного отличался от других ответов, уже опубликованных здесь, я публикую это решение, которое я использовал в то время, здесь, Если кто-нибудь найдет его полезным: (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 ;
}

}

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


Это может быть так же просто, как:

String[] VALUE = new String[] {"AB","BC","CD","AE"};
Arrays.asList(VALUE).contains(s);

проверить это

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
    }
}

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

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");
}

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

Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);

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

String a[] = {"abc","xyz","pqr"};
System.out.println(Arrays.asList(a).contains("abc")); //will return true
System.out.println(Arrays.asList(a).contains("abcd")); // will return false

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