Как определить, содержится ли определенное значение в массиве в Java?
У меня есть массив строк типа String[]
со значениями, например:
public static final String[] VALUES = new String[] {"AB", "BC", "CD", "AE"};
Как мне проверить, содержится ли строка s
в массиве VALUES
? Есть ли эффективный способ сделать это?
3 ответ(ов)
На StackOverflow.com вопрос можно было бы ответить следующим образом:
В вашем коде метод contains
выполняет поиск элемента в массиве, и я заметил, что можно оптимизировать его. Давайте рассмотрим ваш оригинальный код:
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
повторяется для каждого элемента массива, что может быть неэффективно, особенно если массив большой. Вместо этого мы можем выполнить проверку на null
один раз, а затем использовать упрощённое условие внутри цикла.
Вот как может выглядеть улучшенный метод contains2
:
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;
}
В этом варианте, если v
равно null
, мы просто ищем null
в массиве. Если v
не null
, мы проверяем его на равенство с элементами массива. Это позволяет избежать избыточных проверок и делает метод более эффективным.
Если у вас есть дополнительные вопросы или нужно больше пояснений, не стесняйтесь спрашивать!
Для того, чтобы прояснить ситуацию, я провёл тест, сравнивающий три предложенных метода по скорости. Я генерировал случайные целые числа, конвертировал их в строки и добавлял в массив. Затем я искал наибольший возможный номер/строку, что представляло собой худший сценарий для метода asList().contains()
.
При размере массива 10K результаты были следующими:
Сортировка и поиск : 15 мс
Бинарный поиск : 0 мс
asList.contains : 0 мс
При размере массива 100K результаты были следующими:
Сортировка и поиск : 156 мс
Бинарный поиск : 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("Сортировка и поиск : "
+ (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
System.out.println(Arrays.binarySearch(strings, "" + (size - 1)));
System.out.println("Поиск : "
+ (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
System.out.println(Arrays.asList(strings).contains("" + (size - 1)));
System.out.println("Содержит : "
+ (System.currentTimeMillis() - start));
}
}
С помощью 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);
}
Этот метод принимает массив и значение, и возвращает true
, если значение содержится в массиве.
Как объединить два массива в Java?
Как установить Java 8 на Mac
Преобразование 'ArrayList<String>' в 'String[]' в Java
Как создать обобщённый массив в Java?
Java 8: Преобразование List<V> в Map<K, V>