Eu tenho um String[]
com valores como este:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Dado String s
, existe uma boa maneira de testar se VALUES
contém s
?
Eu tenho um String[]
com valores como este:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Dado String s
, existe uma boa maneira de testar se VALUES
contém s
?
Respostas:
Arrays.asList(yourArray).contains(yourValue)
Aviso: isso não funciona para matrizes de primitivas (veja os comentários).
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
Para verificar se uma matriz de int
, double
ou long
contém um valor IntStream
, use DoubleStream
ou LongStream
respectivamente.
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
ArrayList
, mas não java.util.ArrayList
como você espera, a classe verdadeira retornado é: java.util.Arrays.ArrayList<E>
definido como: public class java.util.Arrays {private static class ArrayList<E> ... {}}
.
Matrizes de referência são ruins. Para este caso, estamos atrás de um conjunto. Desde o Java SE 9, temos Set.of
.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
"Dada a string s, existe uma boa maneira de testar se VALUES contém s?"
VALUES.contains(s)
O (1)
O tipo certo , imutável , O (1) e conciso . Bonita.*
Apenas para limpar o código, para começar. Temos (corrigido):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Esta é uma estática mutável que o FindBugs lhe dirá que é muito travessa. Não modifique a estática e não permita que outro código faça isso também. No mínimo absoluto, o campo deve ser privado:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Observe, você pode realmente diminuir o new String[];
bit.)
Matrizes de referência ainda estão ruins e queremos um conjunto:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(Pessoas paranóicas, como eu, podem se sentir mais à vontade se isso estiver envolvido Collections.unmodifiableSet
- pode até ser tornado público.)
(* Para ser um pouco mais sobre a marca, a API de coleções ainda previsivelmente está faltando tipos de coleções imutáveis e a sintaxe ainda é muito detalhada, para o meu gosto.)
Arrays.asList
)?
TreeSet
seria O(log n)
. HashSet
s são dimensionados de forma que o número médio de elementos em um balde seja aproximadamente constante. Pelo menos para matrizes de até 2 ^ 30. Pode haver efeitos de, digamos, caches de hardware que a análise big-O ignora. Também assume que a função hash está funcionando efetivamente.
Você pode usar ArrayUtils.contains
a partir de Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
Observe que esse método retorna false
se a matriz passada for null
.
Também existem métodos disponíveis para matrizes primitivas de todos os tipos.
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
Basta implementá-lo manualmente:
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;
}
Melhoria:
A v != null
condição é constante dentro do método. Ele sempre avalia o mesmo valor booleano durante a chamada do método. Portanto, se a entrada array
for grande, é mais eficiente avaliar essa condição apenas uma vez e podemos usar uma condição simplificada / mais rápida dentro do for
loop com base no resultado. O contains()
método aprimorado :
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;
}
Collection.contains(Object)
Arrays
e ArrayList
se verificar que isso não é necessariamente mais rápido que a versão usada Arrays.asList(...).contains(...)
. A sobrecarga de criação de um ArrayList
é extremamente pequena e ArrayList.contains()
usa um loop mais inteligente (na verdade, ele usa dois loops diferentes) do que o mostrado acima (JDK 7).
Quatro maneiras diferentes de verificar se uma matriz contém um valor
1) Usando a lista:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
2) Usando Set:
public static boolean useSet(String[] arr, String targetValue) {
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
}
3) Usando um loop simples:
public static boolean useLoop(String[] arr, String targetValue) {
for (String s: arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
4) Usando Arrays.binarySearch ():
O código abaixo está errado, está listado aqui para fins de integridade. O binarySearch () só pode ser usado em matrizes classificadas. Você encontrará o resultado estranho abaixo. Essa é a melhor opção quando a matriz é classificada.
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
(a >= 0)
estava correta, basta verificar os documentos , eles dizem "Observe que isso garante que o valor de retorno será> = 0 se e somente se a chave for encontrada".
Se a matriz não for classificada, você terá que repetir tudo e fazer uma chamada para igual a cada um.
Se a matriz estiver classificada, você poderá fazer uma pesquisa binária, há uma na classe Arrays .
De um modo geral, se você for fazer muitas verificações de associação, convém armazenar tudo em um conjunto, não em uma matriz.
Pelo que vale a pena, fiz um teste comparando as 3 sugestões de velocidade. Gerei números inteiros aleatórios, converti-os em uma String e os adicionei a uma matriz. Em seguida, procurei o maior número / string possível, o que seria o pior cenário possível para o asList().contains()
.
Ao usar um tamanho de matriz de 10K, os resultados foram:
Classificação e pesquisa: 15 Pesquisa binária: 0 asList.contains: 0
Ao usar uma matriz de 100K, os resultados foram:
Classificar & Pesquisar: 156 Pesquisa binária: 0 asList.contains: 32
Portanto, se a matriz for criada em ordem classificada, a pesquisa binária será a mais rápida; caso contrário, asList().contains
seria o caminho a seguir. Se você tiver muitas pesquisas, pode valer a pena classificar a matriz para poder usar a pesquisa binária. Tudo depende da sua aplicação.
Eu acho que esses são os resultados que a maioria das pessoas esperaria. Aqui está o código do teste:
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));
}
}
Em vez de usar também a sintaxe de inicialização rápida da matriz, você pode inicializá-la imediatamente como uma Lista de maneira semelhante, usando o método Arrays.asList, por exemplo:
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
Então você pode fazer (como acima):
STRINGS.contains("the string you want to find");
Com o Java 8, você pode criar um fluxo e verificar se alguma entrada no fluxo corresponde "s"
:
String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);
Ou como um método genérico:
public static <T> boolean arrayContains(T[] array, T value) {
return Arrays.stream(array).anyMatch(value::equals);
}
anyMatch
JavaDoc declara isso "...May not evaluate the predicate on all elements if not necessary for determining the result."
, portanto, talvez não seja necessário continuar o processamento após encontrar uma correspondência.
Você pode usar a classe Arrays para executar uma pesquisa binária pelo valor. Se sua matriz não estiver classificada, você precisará usar as funções de classificação na mesma classe para classificar a matriz e, em seguida, pesquise por ela.
ObStupidAnswer (mas acho que há uma lição aqui em algum lugar):
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
Na verdade, se você usar o HashSet <> como proposto por Tom Hawtin, não precisará se preocupar com a classificação, e sua velocidade será a mesma da pesquisa binária em uma matriz pré-definida, provavelmente ainda mais rápida.
Tudo depende de como seu código está configurado, obviamente, mas de onde eu estou, a ordem seria:
Em uma matriz não classificada :
Em uma matriz classificada:
Então, de qualquer forma, HashSet para a vitória.
Se você possui a biblioteca de coleções do Google, a resposta de Tom pode ser muito simplificada usando ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)
Isso realmente remove muita confusão da inicialização proposta
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
Uma solução possível:
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");
}
}
}
Os desenvolvedores costumam:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
O código acima funciona, mas não há necessidade de converter uma lista para definir primeiro. Converter uma lista em um conjunto requer tempo extra. Pode ser tão simples quanto:
Arrays.asList(arr).contains(targetValue);
ou
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
O primeiro é mais legível que o segundo.
Usar um loop simples é a maneira mais eficiente de fazer isso.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Cortesia de Programcreek
No Java 8, use Streams.
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);
Para matrizes de tamanho limitado, use o seguinte (conforme indicado pelo camickr ). Isso é lento para verificações repetidas, especialmente para matrizes mais longas (pesquisa linear).
Arrays.asList(...).contains(...)
Para um desempenho rápido, se você verificar repetidamente um conjunto maior de elementos
Uma matriz é a estrutura errada. Use ae TreeSet
adicione cada elemento a ele. Classifica elementos e possui um exist()
método rápido (pesquisa binária).
Se os elementos forem implementados Comparable
e você desejar TreeSet
classificar adequadamente:
ElementClass.compareTo()
O método deve ser compatível com ElementClass.equals()
: veja Tríades não aparecendo para lutar? (Conjunto Java sem um item)
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));
Caso contrário, use o seu 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);
A recompensa: verifique a existência de algum elemento:
// Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement);
TreeSet
? HashSet
é mais rápido (O (1)) e não requer pedidos.
Tente o seguinte:
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");
}
Use o seguinte (o contains()
método éArrayUtils.in()
neste código):
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 ;
}
}
Como você pode ver no código acima, existem outros métodos utilitários ObjectUtils.equals()
e ArrayUtils.indexOf()
que foram usados em outros locais também.
Verifique isto
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
}
}
else
para cada item que não corresponder (por isso, se você estiver procurando por "AB" nessa matriz, ele irá para lá 3 vezes, já que 3 dos valores não são "AB ").
Arrays.asList () -> chamar o método contains () sempre funcionará, mas um algoritmo de pesquisa é muito melhor, pois você não precisa criar um wrapper de lista leve em torno da matriz, que é o que Arrays.asList () faz .
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.
}
Arrays.asList
não é O (n). É apenas uma embalagem leve. Dê uma olhada na implementação.
Se você não quer que seja sensível a maiúsculas e minúsculas
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Usar Array.BinarySearch(array,obj)
para encontrar o objeto especificado na matriz ou não.
Exemplo:
if (Array.BinarySearch(str, i) > -1)` → true --exists
false - não existe
Array.BinarySearch
e Array.FindIndex
são métodos .NET e não existem em Java.
The array must be sorted prior to making this call. If it is not sorted, the results are undefined.
Crie um booleano inicialmente definido como false. Execute um loop para verificar todos os valores na matriz e comparar com o valor que você está verificando. Se você conseguir uma correspondência, defina booleano como true e interrompa o loop. Em seguida, afirme que o booleano é verdadeiro.
Tente usar o método de teste de predicado Java 8
Aqui está um exemplo completo disso.
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://mytechnologythought.blogspot.com/2019/10/java-8-predicate-test-method-example.html
https://github.com/VipulGulhane1/java8/blob/master/Test.java
o uso de a Spliterator
impede a geração desnecessária de um 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
se search
está contido na matriz
isso faz o trabalho para arrays de primitivas
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 );
…
Como estou lidando com Java de baixo nível usando os tipos primitivos byte e byte [], o melhor que obtive até agora é de bytes-java https://github.com/patrickfav/bytes-java parece um bom trabalho
Você pode verificá-lo por dois métodos
A) Convertendo a matriz em string e, em seguida, verifique a string necessária pelo método .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"));
B) este é um método mais eficaz
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));
}