J'ai un String[]
avec des valeurs telles que:
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
?
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
.
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
Juste pour effacer le code pour commencer. Nous avons (corrigé):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Ceci est une statique modifiable que FindBugs vous dira est très méchant. Il devrait être privé:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Notez que vous pouvez réellement supprimer le bit new String[];
.)
Donc, les tableaux de référence sont mauvais, et en particulier ici nous voulons un ensemble:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(Les paranoïaques, comme moi, peuvent se sentir plus à l'aise si cela était enveloppé dans Collections.unmodifiableSet
- cela pourrait même être rendu public.)
"Étant donné String s, existe-t-il un bon moyen de vérifier si VALUES contient s?"
VALUES.contains(s)
O (1).
Mise à jour: Depuis Java SE 9, nous avons Set.of
.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
Les type correct, immuable, O (1) et concis. Magnifique.
(Pour en savoir un peu plus sur la marque, il était prévisible que les types de collection immuables ne sont pas immuables dans l'API de collections et que la syntaxe est encore beaucoup trop détaillée, à mon goût.)
Vous pouvez utiliser ArrayUtils.contains
de Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
Notez que cette méthode retourne false
si le tableau transmis 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 simplement de le mettre en œuvre à 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 condition v != null
est constante dans la méthode. Il évalue toujours la même valeur booléenne lors de l'appel de la 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 dans la boucle for
en fonction du résultat. La méthode améliorée contains()
:
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;
}
Si le tableau n'est pas trié, vous devrez tout parcourir et faire un appel à égaux sur chacun.
Si le tableau est trié, vous pouvez effectuer une recherche binaire, il y en a une dans la classe Arrays .
En règle générale, si vous allez effectuer beaucoup de vérifications d'adhésion, vous pouvez vouloir tout stocker dans un ensemble, pas dans un tableau.
Quatre manières différentes de vérifier si un tableau contient une valeur
1) Utiliser la liste:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
2) en utilisant l'ensemble:
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 simple boucle:
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 faux, il est listé ici pour être complet. binarySearch () peut UNIQUEMENT être utilisé sur des tableaux triés. Vous trouverez le résultat est 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
Pour ce que ça vaut la peine, j'ai fait un test en 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 recherché le nombre/la chaîne la plus élevée possible, ce qui serait le pire des cas pour la asList().contains()
.
Lors de l'utilisation d'une taille de tableau de 10K, les résultats sont les suivants:
Sort & Search: 15 Recherche binaire: 0 AsList.contains: 0
Lors de l'utilisation d'un tableau de 100K, les résultats sont les suivants:
Sort & Search: 156 Recherche binaire: 0 AsList.contains: 32
Donc, si le tableau est créé dans un ordre trié, la recherche binaire est la plus rapide, sinon la asList().contains
serait la solution. Si vous avez beaucoup de recherches, alors il peut être intéressant de trier le tableau pour pouvoir 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));
}
}
Avec Java 8, vous pouvez créer un flux et vérifier si une entrée du flux correspond à "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);
}
Au lieu d'utiliser également la syntaxe d'initialisation rapide du tableau, vous pouvez l'initialiser immédiatement sous forme de liste de manière similaire à l'aide de 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");
Vous pouvez utiliser le 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 effectuez une recherche.
ObStupidAnswer (mais je pense qu'il y a une leçon 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 le propose Tom Hawtin, vous n'avez pas à vous soucier du tri et votre vitesse est identique à celle de la recherche binaire sur un tableau pré-trié, probablement même plus rapide.
Tout dépend de la manière dont votre code est configuré, évidemment, mais dans l'ordre où je me trouve, l'ordre serait:
Sur un non trié tableau:
Sur un tableau trié:
Alors de toute façon, HashSet pour la victoire.
Si vous avez la bibliothèque de collections Google, la réponse de Tom peut être simplifiée beaucoup 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.
Dans 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);
Le moyen le plus efficace consiste à utiliser une boucle simple.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Courtoisie à Programcreek
Pour les tableaux de longueur limitée, utilisez ce qui suit (comme indiqué par camickr ). Ceci est lent pour les contrôles répétés, en particulier pour les tableaux plus longs (recherche linéaire).
Arrays.asList(...).contains(...)
Pour des performances rapides si vous vérifiez à plusieurs reprises par rapport à un ensemble d'éléments plus volumineux
Un tableau est la mauvaise structure. Utilisez un TreeSet
et ajoutez-y chaque élément. Il trie les éléments et utilise une méthode rapide exist()
(recherche binaire).
Si les éléments implémentent Comparable
& vous voulez que le TreeSet
soit trié en conséquence:
La méthode ElementClass.compareTo()
doit être compatible avec ElementClass.equals()
: voir les triades ne s'affichent pas pour combattre? (Java met un élément manquant)
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 votre propre 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érifier l'existence d'un élément:
// Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement);
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 les éléments suivants (la méthode contains()
est 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 constater dans le code ci-dessus, il existe d'autres méthodes utilitaires ObjectUtils.equals()
et ArrayUtils.indexOf()
qui étaient également utilisées à d'autres endroits.
Arrays.asList () -> puis l'appel de 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.
}
Si vous ne voulez pas qu'il soit sensible à la casse
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Utilisez Array.BinarySearch(array,obj)
pour trouver ou non l'objet donné dans un tableau.
Exemple:
if (Array.BinarySearch(str, i) > -1)` → true --exists
faux - n'existe pas
Vérifie ç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
}
}
Créez un booléen initialement défini sur false. Exécutez une boucle pour vérifier chaque valeur du tableau et comparez-la à la valeur que vous vérifiez. Si vous obtenez une correspondance, définissez boolean sur true et arrêtez la mise en boucle. Ensuite, affirmez que le booléen est vrai.