arrays array - Como determinar se uma matriz contém um valor específico em Java?





string objetos (21)


Estou surpreso que ninguém sugeriu simplesmente 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 condição v != null é constante dentro do método, sempre avalia o mesmo valor booleano durante a chamada do método. Portanto, se a array entrada for grande, é mais eficiente avaliar essa condição apenas uma vez e podemos usar uma condição simplificada / mais rápida dentro do loop for base no resultado. O método contains() 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;
}

Eu tenho um String[] com valores como:

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 ?




  1. Para matrizes de comprimento limitado, use o seguinte (conforme fornecido por camickr ). Isso é lento para verificações repetidas, especialmente para matrizes mais longas (pesquisa linear).

     Arrays.asList(...).contains(...)
  2. Para obter um desempenho rápido, se você verificar repetidamente um conjunto maior de elementos

    • Uma matriz é a estrutura errada. Use um TreeSet e adicione cada elemento a ele. Ele classifica os elementos e possui um método fast exist() (pesquisa binária).

    • Se os elementos implementarem o Comparable e você quiser que o TreeSet classificado de acordo:

      ElementClass.compareTo() método ElementClass.compareTo() deve ser compatível com ElementClass.equals() : veja Triads não aparecer para lutar? (Java Set faltando 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 seu próprio 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);
    • O pagamento: verifique a existência de algum elemento:

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



Estou muito atrasado para participar dessa discussão, mas como a minha abordagem para resolver esse problema, quando o enfrentei há alguns anos, era um pouco diferente das outras respostas já postadas aqui, estou postando a solução que usei na época, aqui, no caso de alguém achar útil: (O método contains() é 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 lugares também.




Crie um booleano inicialmente configurado como false. Execute um loop para verificar todos os valores na matriz e compare com o valor que você está verificando. Se você conseguir uma correspondência, defina booleano como true e pare o loop. Então afirme que o booleano é verdadeiro.




Tente isto:

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



Na verdade, se você usar o HashSet como o Tom Hawtin propôs você não precisa se preocupar com a classificação e sua velocidade é a mesma que a da Pesquisa Binária em uma matriz pré-determinada, provavelmente ainda mais rápida.

Tudo depende de como seu código está configurado, obviamente, mas de onde eu estou, o pedido seria:

Em uma matriz UNsorted:

  1. HashSet
  2. asList
  3. classificar e binário

Em uma matriz ordenada:

  1. HashSet
  2. Binário
  3. asList

Então, de qualquer forma, HashSet ftw




Quatro maneiras diferentes de verificar se um array contém um valor

1) Usando 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 por completo. binarySearch () só pode ser usado em matrizes ordenadas. 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;
        }

Exemplo Rápido:

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



Em vez de usar a sintaxe de initialsation de matriz rápida, você poderia apenas inicializá-la como uma List imediatamente 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");




Arrays.asList(yourArray).contains(yourValue)

Aviso: isso não funciona para matrizes de primitivos (veja os comentários).

Desde o java-8 agora você pode usar o Streams.

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, use IntStream , DoubleStream ou LongStream respectivamente.

Exemplo

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



Se a matriz não estiver classificada, você terá que iterar tudo e fazer uma chamada para igual em cada um.

Se a matriz estiver ordenada, você pode fazer uma pesquisa binária, há uma na classe Arrays .

De um modo geral, se você fizer muitas verificações de associação, talvez queira armazenar tudo em um conjunto, não em uma matriz.




Se você tiver a biblioteca de coleções do Google, a resposta de Tom pode ser muito simplificada usando o ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)

Isso realmente remove muita desordem da inicialização proposta

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



Apenas para limpar o código para começar. Nós temos (corrigido):

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

Esta é uma estática mutável que o FindBugs irá dizer que é muito desobediente. Deve ser privado:

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

(Nota, você pode realmente largar o new String[]; bit new String[]; )

Então, as matrizes de referência são ruins e, em particular, aqui 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 for envolto em Collections.unmodifiableSet - pode até ser tornado público.)

"Dado String s, existe uma boa maneira de testar se VALUES contém s?"

VALUES.contains(s)

O (1)




Para o que vale a pena eu fiz um teste comparando as 3 sugestões de velocidade. Eu gerei números inteiros aleatórios, converti-os em uma String e os adicionei a uma matriz. Em seguida, procurei pelo 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 são:

Sort & Search   : 15
Binary Search   : 0
asList.contains : 0

Ao usar uma matriz de 100 K, os resultados são:

Sort & Search   : 156
Binary Search   : 0
asList.contains : 32

Portanto, se a matriz for criada em ordem de classificação, a pesquisa binária será a mais rápida, caso contrário, o asList (). Contains será o caminho a seguir. Se você tiver muitas pesquisas, poderá 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 de 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));
    }
}



Arrays.asList () -> então chamar o método contains () sempre funcionará, mas um algoritmo de busca é muito melhor já que você não precisa criar um wrapper de lista leve ao redor do array, que é o que o 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.
}



Os desenvolvedores geralmente fazem:

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 como:

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.




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



Com o Java 8, você pode criar um fluxo e verificar se alguma entrada no fluxo corresponde a "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);
}



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



Verificar isso

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



Eu só notei que você fez referência ao meu artigo .

O Java Spec diz que tudo em Java é passado por valor. Não existe "pass-by-reference" em Java.

A chave para entender isso é que algo como

Dog myDog;

não é um cachorro; Na verdade, é um ponteiro para um cão.

O que isso significa é quando você tem

Dog myDog = new Dog("Rover");
foo(myDog);

você está essencialmente passando o endereço do objeto Dog criado para o método foo .

(Eu digo essencialmente porque os ponteiros Java não são endereços diretos, mas é mais fácil pensar neles dessa maneira)

Suponha que o objeto Dog resida no endereço de memória 42. Isso significa que passamos 42 para o método.

se o Método fosse definido como

public void foo(Dog someDog) {
    someDog.setName("Max");     // AAA
    someDog = new Dog("Fifi");  // BBB
    someDog.setName("Rowlf");   // CCC
}

vamos ver o que está acontecendo.

  • o parâmetro someDog está configurado para o valor 42
  • na linha "AAA"
    • someDog é seguido pelo Dog para o qual aponta (o objeto Dog no endereço 42)
    • aquele Dog (aquele no endereço 42) é solicitado a mudar seu nome para Max
  • na linha "BBB"
    • um novo Dog é criado. Digamos que ele esteja no endereço 74
    • nós atribuímos o parâmetro someDog para 74
  • na linha "CCC"
    • someDog é seguido pelo Dog para o qual aponta (o objeto Dog no endereço 74)
    • aquele Dog (o do endereço 74) é solicitado a mudar seu nome para Rowlf
  • então voltamos

Agora vamos pensar sobre o que acontece fora do método:

O myDog mudou?

Há a chave.

Tendo em mente que o myDog é um ponteiro , e não um Dog real, a resposta é NÃO. myDog ainda tem o valor 42; ainda está apontando para o Dog original (mas note que por causa da linha "AAA", seu nome é agora "Max" - ainda o mesmo Cão; o valor do myDog não mudou).

É perfeitamente válido seguir um endereço e mudar o que está no final dele; isso não altera a variável, entretanto.

Java funciona exatamente como C. Você pode atribuir um ponteiro, passar o ponteiro para um método, seguir o ponteiro no método e alterar os dados que foram apontados. No entanto, você não pode alterar onde esse ponteiro aponta.

Em C ++, Ada, Pascal e outras linguagens que suportam pass-by-reference, você pode realmente mudar a variável que foi passada.

Se Java tivesse semântica de passagem por referência, o método foo que definimos acima teria mudado para onde myDog estava apontando quando atribuiu someDog na linha BBB.

Pense nos parâmetros de referência como sendo aliases para a variável transmitida. Quando esse alias é atribuído, a variável que foi transmitida também é atribuída.







java arrays