J'ai un String[]
avec des valeurs comme ça:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Étant donné String s
, existe-t-il un bon moyen de vérifier si VALUES
contient s
?
J'ai un String[]
avec des valeurs comme ça:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Étant donné String s
, existe-t-il un bon moyen de vérifier si VALUES
contient s
?
Réponses:
Arrays.asList(yourArray).contains(yourValue)
Attention: cela ne fonctionne pas pour les tableaux de primitives (voir les commentaires).
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
Pour vérifier si un tableau de int
, double
ou long
contient une valeur, utilisez IntStream
, DoubleStream
ou LongStream
respectivement.
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
ArrayList
, mais pas java.util.ArrayList
comme prévu, la vraie classe retournée est: java.util.Arrays.ArrayList<E>
définie comme suit: public class java.util.Arrays {private static class ArrayList<E> ... {}}
.
Les tableaux de référence sont mauvais. Pour ce cas, nous recherchons un ensemble. Depuis Java SE 9, nous l'avons Set.of
.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
"Étant donné String s, existe-t-il un bon moyen de tester si VALUES contient s?"
VALUES.contains(s)
O (1).
Le bon type , immuable , O (1) et concis . Beau.*
Juste pour effacer le code pour commencer. Nous avons (corrigé):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Il s'agit d'une statique mutable que FindBugs vous dira très coquine. Ne modifiez pas la statique et n'autorisez pas d'autres codes à le faire également. Au minimum, le champ doit être privé:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Remarque, vous pouvez réellement laisser tomber le new String[];
bit.)
Les tableaux de référence sont toujours mauvais et nous voulons un ensemble:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(Les personnes paranoïaques, comme moi, pourraient se sentir plus à l'aise si cela était enveloppé Collections.unmodifiableSet
- cela pourrait même être rendu public.)
(* Pour être un peu plus sur la marque, il est prévisible que l'API des collections manque encore de types de collections immuables et la syntaxe est encore beaucoup trop verbeuse, à mon goût.)
Arrays.asList
)?
TreeSet
serait O(log n)
. HashSet
s sont mis à l'échelle de telle sorte que le nombre moyen d'éléments dans un compartiment est à peu près constant. Au moins pour les tableaux jusqu'à 2 ^ 30. Il peut y avoir des effets provenant, par exemple, de caches matériels que l'analyse big-O ignore. Suppose également que la fonction de hachage fonctionne efficacement.
Vous pouvez utiliser ArrayUtils.contains
depuis Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
Notez que cette méthode retourne false
si le tableau passé est null
.
Il existe également des méthodes disponibles pour les tableaux primitifs de toutes sortes.
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
Il suffit de l'implémenter à la main:
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;
}
Amélioration:
La v != null
condition est constante à l'intérieur de la méthode. Il évalue toujours la même valeur booléenne lors de l'appel de méthode. Donc, si l'entrée array
est grande, il est plus efficace d'évaluer cette condition une seule fois, et nous pouvons utiliser une condition simplifiée / plus rapide à l'intérieur de la for
boucle en fonction du résultat. La contains()
méthode améliorée :
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
et ArrayList
il s'avère que ce n'est pas nécessairement plus rapide que la version utilisant Arrays.asList(...).contains(...)
. La surcharge de la création d'un ArrayList
est extrêmement petite et ArrayList.contains()
utilise une boucle plus intelligente (en fait, elle utilise deux boucles différentes) que celle illustrée ci-dessus (JDK 7).
Quatre façons différentes de vérifier si un tableau contient une valeur
1) Utilisation de la liste:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
2) Utilisation de Set:
public static boolean useSet(String[] arr, String targetValue) {
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
}
3) En utilisant une boucle simple:
public static boolean useLoop(String[] arr, String targetValue) {
for (String s: arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
4) Utilisation de Arrays.binarySearch ():
Le code ci-dessous est incorrect, il est répertorié ici pour être complet. binarySearch () ne peut être utilisé que sur des tableaux triés. Vous trouverez le résultat bizarre ci-dessous. C'est la meilleure option lorsque le tableau est trié.
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)
était correcte, il suffit de vérifier les documents , ils disent "Notez que cela garantit que la valeur de retour sera> = 0 si et seulement si la clé est trouvée".
Si le tableau n'est pas trié, vous devrez parcourir tout et faire un appel à égal sur chacun.
Si le tableau est trié, vous pouvez faire une recherche binaire, il y en a un dans la classe Arrays .
De manière générale, si vous devez effectuer de nombreuses vérifications d'appartenance, vous souhaiterez peut-être tout stocker dans un ensemble, pas dans un tableau.
Pour ce que ça vaut j'ai fait un test comparant les 3 suggestions de vitesse. J'ai généré des entiers aléatoires, les ai convertis en chaîne et les ai ajoutés à un tableau. J'ai ensuite cherché le nombre / chaîne le plus élevé possible, ce qui serait le pire des cas pour le asList().contains()
.
Lors de l'utilisation d'une taille de tableau de 10 Ko, les résultats étaient les suivants:
Trier et rechercher: 15 Recherche binaire: 0 asList.contains: 0
Lors de l'utilisation d'un tableau 100K, les résultats étaient les suivants:
Tri & Recherche: 156 Recherche binaire: 0 asList.contient: 32
Donc, si le tableau est créé dans un ordre trié, la recherche binaire est la plus rapide, sinon ce asList().contains
serait la voie à suivre. Si vous avez plusieurs recherches, il peut être utile de trier le tableau afin que vous puissiez utiliser la recherche binaire. Tout dépend de votre application.
Je pense que ce sont les résultats auxquels la plupart des gens s'attendent. Voici le code de test:
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));
}
}
Au lieu d'utiliser également la syntaxe d'initialisation rapide des tableaux, vous pouvez simplement l'initialiser sous forme de liste de la même manière en utilisant la méthode Arrays.asList, par exemple:
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
Ensuite, vous pouvez faire (comme ci-dessus):
STRINGS.contains("the string you want to find");
Avec Java 8, vous pouvez créer un flux et vérifier si des entrées dans le flux correspondent "s"
:
String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);
Ou comme méthode générique:
public static <T> boolean arrayContains(T[] array, T value) {
return Arrays.stream(array).anyMatch(value::equals);
}
anyMatch
JavaDoc le déclare "...May not evaluate the predicate on all elements if not necessary for determining the result."
, il n'est donc pas nécessaire de poursuivre le traitement après avoir trouvé une correspondance.
Vous pouvez utiliser la classe Arrays pour effectuer une recherche binaire de la valeur. Si votre tableau n'est pas trié, vous devrez utiliser les fonctions de tri de la même classe pour trier le tableau, puis le parcourir.
ObStupidAnswer (mais je pense qu'il y a une leçon ici quelque part):
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
En fait, si vous utilisez HashSet <String> comme Tom Hawtin l'a proposé, vous n'avez pas à vous soucier du tri, et votre vitesse est la même qu'avec la recherche binaire sur un tableau pré-trié, probablement encore plus rapide.
Tout dépend de la façon dont votre code est configuré, évidemment, mais d'où je me situe, l'ordre serait:
Sur un tableau non trié :
Sur un tableau trié:
Donc de toute façon, HashSet pour la victoire.
Si vous disposez de la bibliothèque de collections Google, la réponse de Tom peut être simplifiée en utilisant ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)
Cela supprime vraiment beaucoup d'encombrement de l'initialisation proposée
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
Une solution possible:
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");
}
}
}
Les développeurs font souvent:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
Le code ci-dessus fonctionne, mais il n'est pas nécessaire de convertir une liste à définir en premier. La conversion d'une liste en un ensemble nécessite du temps supplémentaire. Cela peut être aussi simple que:
Arrays.asList(arr).contains(targetValue);
ou
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
Le premier est plus lisible que le second.
L'utilisation d'une boucle simple est le moyen le plus efficace de le faire.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Courtoisie de Programcreek
En Java 8, utilisez 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);
Pour les tableaux de longueur limitée, utilisez ce qui suit (comme indiqué par camickr ). Ceci est lent pour les vérifications répétées, en particulier pour les tableaux plus longs (recherche linéaire).
Arrays.asList(...).contains(...)
Pour des performances rapides si vous effectuez plusieurs vérifications par rapport à un ensemble d'éléments plus important
Un tableau n'est pas la bonne structure. Utilisez a TreeSet
et ajoutez-y chaque élément. Il trie les éléments et dispose d'une exist()
méthode rapide (recherche binaire).
Si les éléments implémentent Comparable
et que vous voulezTreeSet
trier en conséquence:
ElementClass.compareTo()
La méthode doit être compatible avec ElementClass.equals()
: voir Triades ne se présentant pas pour se battre? (Jeu Java manquant un élément)
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));
Sinon, utilisez le vôtre 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);
Le gain: vérifiez l'existence d'un élément:
// Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement);
TreeSet
? HashSet
est plus rapide (O (1)) et ne nécessite pas de commande.
Essaye ça:
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");
}
Utilisez ce qui suit (la contains()
méthode se trouve ArrayUtils.in()
dans ce code):
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 ;
}
}
Comme vous pouvez le voir dans le code ci-dessus, il existe d'autres méthodes utilitaires ObjectUtils.equals()
et ArrayUtils.indexOf()
qui ont également été utilisées à d'autres endroits.
Vérifiez ça
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
pour chaque élément qui ne correspond pas (donc si vous recherchez "AB" dans ce tableau, il y ira 3 fois, car 3 des valeurs ne sont pas "AB" ").
Arrays.asList () -> puis appeler la méthode contains () fonctionnera toujours, mais un algorithme de recherche est bien meilleur car vous n'avez pas besoin de créer un wrapper de liste léger autour du tableau, ce que fait Arrays.asList () .
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'est pas O (n). C'est juste un emballage léger. Jetez un oeil à la mise en œuvre.
Si vous ne voulez pas qu'il soit sensible à la casse
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Utilisation Array.BinarySearch(array,obj)
pour trouver l'objet donné dans le tableau ou non.
Exemple:
if (Array.BinarySearch(str, i) > -1)` → true --exists
false - n'existe pas
Array.BinarySearch
et Array.FindIndex
sont des méthodes .NET et n'existent pas en Java.
The array must be sorted prior to making this call. If it is not sorted, the results are undefined.
Essayez d'utiliser la méthode de test des prédicats Java 8
En voici un exemple complet.
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
l'utilisation d'un Spliterator
empêche la génération inutile d'un 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
si search
est contenu dans le tableau
cela fait le travail pour les tableaux de primitives
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 );
…
Comme je traite avec Java de bas niveau en utilisant les types primitifs octet et octet [], le meilleur que j'ai obtenu jusqu'à présent est de bytes-java https://github.com/patrickfav/bytes-java semble un bon travail
Vous pouvez le vérifier par deux méthodes
A) En convertissant le tableau en chaîne, puis vérifiez la chaîne requise par la méthode .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) c'est une méthode plus efficace
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));
}