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



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



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


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

930   27  

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

благоустройство:

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

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

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. sort & Binary

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

  1. HashSet
  2. Binary
  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;

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

In 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) для нахождения данного объекта в массив или нет. Например:

if (Array.BinarySearch(str, i) > -1) -- > true -- существует

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

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

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

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

вот мой простой код с использованием класса массивов из пакета 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 и остановите цикл. Затем утверждают, что логическое значение истинно.

Comments

    Ничего не найдено.