Java, controllo semplificato se l'array int contiene int


94

Fondamentalmente il mio amico ha detto che potrei accorciare il mio codice usando un modo diverso di verificare se un array int contiene un int, anche se non mi dice di cosa si tratta: P.

Attuale:

public boolean contains(final int[] array, final int key) {
    for (final int i : array) {
        if (i == key) {
            return true;
        }
    }
    return false;
}

Ho anche provato questo, anche se per qualche motivo restituisce sempre falso.

public boolean contains(final int[] array, final int key) {
    return Arrays.asList(array).contains(key);
}

Qualcuno può aiutarmi?

Grazie.


8
La tua chiamata Arrays.asList (...) accetta un vararg, ovvero racchiude il numero arbitrario di argomenti che potresti passare in un elenco. Nel tuo caso, stai ottenendo un elenco di array con un singolo elemento e questo elenco ovviamente non contiene l'int.
sarcan

Il tuo commento significa che cosa adesso?
sarcan

Hashsetrisposta del meccanismo di riesecuzione basato sul controllo . È il modo più veloce.
Amit Deshpande

Non vedo alcun motivo per rendere il tuo codice originale più corto poiché il tuo argomento è un array primitivo e il tuo codice è molto chiaro e diretto. ArrayListl'implementazione sta facendo lo stesso.
Genzer

Non renderei il tuo codice più breve. (1) arraylist fa la stessa cosa che hai fatto tu. (2) - La cosa più importante è che il codice abbreviato utilizzando Arrays.asList crea un nuovo oggetto, che potrebbe essere un problema all'interno di un codice critico per le prestazioni. Il primo frammento di codice è la cosa migliore che puoi fare.
Martin Podval

Risposte:


38

Ecco la soluzione Java 8

public static boolean contains(final int[] arr, final int key) {
    return Arrays.stream(arr).anyMatch(i -> i == key);
}

63

Potresti semplicemente usare ArrayUtils.containsda Apache Commons Lang library.

public boolean contains(final int[] array, final int key) {     
    return ArrayUtils.contains(array, key);
}

1
Finché utilizzi ArrayUtils, c'è qualche motivo per non utilizzare ArrayUtils.contains
mjohnsonengr

2
Nessun motivo :)
Reimeus

20
Vale la pena notare che ArrayUtils.contains()fa parte della Apache Commons Langlibreria. Anche se è un'ottima libreria, probabilmente non è ancora una buona idea aggiungere una dipendenza esterna solo per verificare se l'array contiene un elemento: D
Krzysiek

2
ArrayUtils è un ricordo del passato. Java 8+ e Guava hanno chicche davvero sorprendenti !!
TriCore

34

È perché Arrays.asList(array)ritorno List<int[]>. arrayargomento è trattato come un valore che vuoi racchiudere (ottieni un elenco di array di int), non come vararg.

Nota che fa il lavoro con i tipi di oggetto (non primitive):

public boolean contains(final String[] array, final String key) {
    return Arrays.asList(array).contains(key);
}

o anche:

public <T>  boolean contains(final T[] array, final T key) {
    return Arrays.asList(array).contains(key);
}

Ma non puoi avere List<int>e l'autoboxing non funziona qui.


1
Perché l'autoboxing non funziona, è perché è dichiarato definitivo?
subhashis

19

Guava offre metodi aggiuntivi per i tipi primitivi. Tra questi un metodo contiene che accetta gli stessi argomenti dei tuoi.

public boolean contains(final int[] array, final int key) {
    return Ints.contains(array, key);
}

Potresti anche importare staticamente la versione guava.

Vedi Guava Primitives Explained


18

Un modo diverso:

public boolean contains(final int[] array, final int key) {  
     Arrays.sort(array);  
     return Arrays.binarySearch(array, key) >= 0;  
}  

Ciò modifica l'array passato. Avresti la possibilità di copiare l'array e lavorare sull'array originale cioè int[] sorted = array.clone();
Ma questo è solo un esempio di codice breve. Il tempo di esecuzione è O(NlogN)mentre la tua strada èO(N)


30
Penso che sarei sorpreso se un containsmetodo modificasse il mio array.
Zong

@ZongLi: Questo è solo un esempio per l'OP. OP aggiornato se stiamo facendo il pelo
nell'uovo

5
Da javadoc di binarySearch (): "il valore restituito sarà> = 0 se e solo se la chiave viene trovata." quindi Arrays.binarySearch (array, key)> = 0 dovrebbe essere restituito!
icza

Supplemento: il valore di ritorno di binarySearch () è (- (punto di inserimento) - 1) se la chiave non è contenuta, il che potrebbe essere un valore diverso da -1.
icza

Questo non può essere -1se intende essere vero. "Il punto di inserimento è definito come il punto in cui la chiave verrebbe inserita nell'elenco: l'indice del primo elemento maggiore della chiave, o list.size () se tutti gli elementi nell'elenco sono inferiori alla chiave specificata. ". Ho bisogno di dirlo >= 0.
Brian


1

1. usi una tantum

List<T> list=Arrays.asList(...)
list.contains(...)

2.usare HashSet per la considerazione delle prestazioni se si utilizza più di una volta.

Set <T>set =new HashSet<T>(Arrays.asList(...));
set.contains(...)

1

Prova questo:

public static void arrayContains(){
    int myArray[]={2,2,5,4,8};

    int length=myArray.length;

    int toFind = 5;
    boolean found = false;

    for(int i = 0; i < length; i++) {
        if(myArray[i]==toFind) {
            found=true;
        }
    }

    System.out.println(myArray.length);
    System.out.println(found); 
}

1

Puoi convertire il tuo array int primitivo in un elenco di numeri interi utilizzando il codice Java 8 di seguito,

List<Integer> arrayElementsList = Arrays.stream(yourArray).boxed().collect(Collectors.toList());

Quindi usa il contains()metodo per verificare se l'elenco contiene un particolare elemento,

boolean containsElement = arrayElementsList.contains(key);

0

questo ha funzionato in java 8

public static boolean contains(final int[] array, final int key)
{
return Arrays.stream(array).anyMatch(n->n==key);
}

Dovrebbe tornare immediatamente alla prima corrispondenza, invece questo analizzerà ancora tutti gli elementi nell'array, anche se ha trovato la corrispondenza. (Considera una serie di articoli trilion)
TriCore

Hai ragione, prova questo booleano statico pubblico contiene (final int [] array, final int key) {return Arrays.stream (array) .anyMatch (n-> n == key); }
Farhad Baghirov

Java 8 stream anyMatch è un'operazione di cortocircuito e non eseguirà la scansione di tutti gli elementi nell'array.
LordParsley

@LordParsley L'obiettivo sopra il codice è controllare l'elemento nell'array, non scansionare tutti gli elementi dell'array.
Farhad Baghirov

Mi dispiace, vedo che la risposta è stata modificata. Stavo solo ribadendo che era corretto in quanto non sarà necessario scansionare tutto se trova una parte.
LordParsley

0

Puoi usare java.util.Arraysclass per trasformare l'array T[?]in un List<T>oggetto con metodi come contains:

Arrays.asList(int[] array).contains(int key);

-1

A seconda di quanto sarà grande il tuo array di int, otterrai prestazioni molto migliori se usi le collezioni e .containsinvece di iterare sull'array un elemento alla volta:

import static org.junit.Assert.assertTrue;
import java.util.HashSet;

import org.junit.Before;
import org.junit.Test;

public class IntLookupTest {

int numberOfInts = 500000;
int toFind = 200000;
int[] array;

HashSet<Integer> intSet;

@Before
public void initializeArrayAndSet() {
    array = new int[numberOfInts];
    intSet = new HashSet<Integer>();
    for(int i = 0; i < numberOfInts; i++) {
        array[i] = i;
        intSet.add(i);
    }
}

@Test
public void lookupUsingCollections() {
    assertTrue(intSet.contains(toFind));
}

@Test
public void iterateArray() {
    assertTrue(contains(array, toFind));

}

public boolean contains(final int[] array, final int key) {
    for (final int i : array) {
        if (i == key) {
            return true;
        }
    }
    return false;
}
}

-1

Soluzione n. 1

Poiché la domanda originale vuole solo una soluzione semplificata (e non una più veloce), ecco una soluzione di una riga:

public boolean contains(int[] array, int key) {
    return Arrays.toString(array).matches(".*[\\[ ]" + key + "[\\],].*");
}

Spiegazione: Javadoc degli Arrays.toString()stati il ​​risultato è racchiuso tra parentesi quadre e gli elementi adiacenti sono separati dai caratteri "," (una virgola seguita da uno spazio). Quindi possiamo contare su questo. Per prima cosa convertiamo arrayin una stringa, quindi controlliamo se keyè contenuto in questa stringa. Ovviamente non possiamo accettare "sotto-numeri" (es. "1234" contiene "23"), quindi dobbiamo cercare schemi in cui il keyè preceduto da una parentesi aperta o uno spazio e seguito da una parentesi chiusa o una virgola.

Nota: il pattern regexp utilizzato gestisce correttamente anche i numeri negativi (la cui rappresentazione di stringa inizia con un segno meno).

Soluzione n. 2

Questa soluzione è già pubblicata ma contiene errori, quindi inserisco la soluzione corretta:

public boolean contains(int[] array, int key) {
    Arrays.sort(array);
    return Arrays.binarySearch(array, key) >= 0;
}

Anche questa soluzione ha un effetto collaterale: modifica il array(lo ordina).


La mano delle stringhe è generalmente costosa, perché qualcuno dovrebbe trattare gli int come stringhe?
Denys Vitali

@DenysVitali Perché op ha già una soluzione funzionante ed efficiente e sta cercando una soluzione più breve . E questi sono più brevi. Questa domanda non riguarda le prestazioni.
icza

Avrei dovuto fraintendere la domanda allora, scusa per averlo chiesto
Denys Vitali

-5

Prova Integer.parseInt()a farlo .....

public boolean chkInt(final int[] array){
    int key = false;

    for (Integer i : array){


          try{

                   Integer.parseInt(i);
                   key = true;
                   return key;

             }catch(NumberFormatException ex){

                   key = false;

                   return key;

              }


     }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.