Как определить, содержит ли массив определенное значение в Java? - PullRequest
2115 голосов
/ 15 июля 2009

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

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

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

Ответы [ 25 ]

2730 голосов
/ 15 июля 2009
Arrays.asList(yourArray).contains(yourValue)

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


С теперь вы можете использовать потоки.

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);
339 голосов
/ 15 июля 2009

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

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 - это могло бы даже быть обнародовано.)

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

VALUES.contains(s)

O (1).

Обновление: Начиная с Java SE 9 у нас есть Set.of.

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

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

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

189 голосов
/ 31 мая 2011

Вы можете использовать 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.
}
151 голосов
/ 28 сентября 2012

Просто выполните это вручную:

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;
}
68 голосов
/ 15 июля 2009

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

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

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

67 голосов
/ 07 мая 2014

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

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) Использование Arrays.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
48 голосов
/ 15 июля 2009

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

При использовании размера массива 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));
    }
}
34 голосов
/ 13 марта 2014

С 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);
}
33 голосов
/ 20 января 2011

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

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

Тогда вы можете сделать (как выше):

STRINGS.contains("the string you want to find");
26 голосов
/ 15 июля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...