web-dev-qa-db-ja.com

Javaの配列に特定の値が含まれているかどうかを判断する方法

以下のような値のString[]があります。

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

String sを考えて、VALUESsを含んでいるかどうかをテストする良い方法はありますか?

2084
Mike Sickler
Arrays.asList(yourArray).contains(yourValue)

警告:これはプリミティブの配列に対しては機能しません(コメントを参照)。


Java-8 以降、Streamsを使用できるようになりました。

String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);

intdoubleまたはlongの配列に値が含まれているかどうかを確認するには、それぞれIntStreamDoubleStreamまたはLongStreamを使用します。

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

まず最初にコードをクリアします。我々は(修正)を持っています:

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

これは、FindBugsがあなたに教えてくれるであろう不定の静的なものです。それはプライベートであるべきです:

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

(注、実際にはnew String[];ビットをドロップすることができます。)

そのため、参照配列は良くありません。特にここでは集合が欲しいのです。

private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
     new String[] {"AB","BC","CD","AE"}
));

(私のような妄想的な人々は、これがCollections.unmodifiableSetに包まれていればもっと安らぎを感じるかもしれません - それは公にされることさえ可能です。)

「Stringが与えられた場合、VALUESにsが含まれているかどうかをテストする良い方法はありますか?」

VALUES.contains(s)

O(1).

更新: Java SE 9以降、Set.ofがあります。

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

正しい型 不変 O(1) および 簡潔 。綺麗な。

(もう少しブランドになるには、collections APIには不変のコレクション型がまだ欠けていて、構文はまだ冗長すぎるので、私の好みではありません。)

330

Apache Commons Lang からArrayUtils.containsを使うことができます

public static boolean contains(Object[] array, Object objectToFind)

渡された配列がfalseの場合、このメソッドはnullを返します。

すべての種類のプリミティブ配列に利用できるメソッドもあります。

例:

String[] fieldsToInclude = { "id", "name", "location" };

if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
    // Do some stuff.
}
186
Intracer

単にそれを手で実装するだけです:

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

改善:

v != null条件はメソッド内で一定です。メソッド呼び出し中は常に同じブール値に評価されます。したがって、入力arrayが大きい場合は、この条件を1回だけ評価するほうが効率的です。その結果に基づいて、forループ内で単純化された/より速い条件を使用できます。改良された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;
}
150
icza

配列がソートされていない場合は、すべてを反復処理し、それぞれに対してequalsを呼び出す必要があります。

配列がソートされている場合は、バイナリ検索ができます。 Arrays クラスにあります。

一般的に言って、あなたがたくさんのメンバーシップチェックをするつもりなら、あなたは配列ではなくセットにすべてを保存したいかもしれません。

67
Uri

配列に値が含まれているかどうかを確認する4つの方法

1)リストを使う

public static boolean useList(String[] arr, String targetValue) {
    return Arrays.asList(arr).contains(targetValue);
}

2)セットを使う:

public static boolean useSet(String[] arr, String targetValue) {
    Set<String> set = new HashSet<String>(Arrays.asList(arr));
    return set.contains(targetValue);
}

3)単純なループを使う

public static boolean useLoop(String[] arr, String targetValue) {
    for (String s: arr) {
        if (s.equals(targetValue))
            return true;
    }
    return false;
}

4)Arrays.binarySearch()を使う:

以下のコードは間違っています、完全を期すためにここにリストされています。 binarySearch()はソートされた配列に対してのみ使用できます。あなたは結果が以下で変であるのがわかるでしょう。これは配列がソートされているときの最善の選択肢です。

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
64

それが価値があるもののために私はスピードのための3つの提案を比較するテストを実行しました。ランダムな整数を生成し、それらを文字列に変換して配列に追加しました。私はそれからasList().contains()のための最悪のシナリオであろう可能な最も高い数/ストリングを探しました。

10Kの配列サイズを使用した場合の結果は次のとおりです。

並べ替えと検索:15 
バイナリ検索:0 
 asList.contains:0 

100Kアレイを使用した場合の結果は以下のとおりです。

並べ替えと検索:156 
バイナリ検索:0 
 asList.contains:32 

そのため、配列がソートされた順序で作成されている場合はバイナリ検索が最速です。それ以外の場合はasList().containsが最適な方法です。たくさんの検索がある場合は、二分検索を使用できるように配列をソートするのが有益かもしれません。それはすべてあなたのアプリケーションに依存します。

私はそれらがほとんどの人が期待する結果であると思うでしょう。これがテストコードです。

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));
    }
}
47
camickr

Java 8では、ストリームを作成し、そのストリーム内のいずれかのエントリが"s"と一致するかどうかを確認できます。

String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);

または一般的な方法として:

public static <T> boolean arrayContains(T[] array, T value) {
    return Arrays.stream(array).anyMatch(value::equals);
}
33
assylias

クイック配列初期化構文も使用する代わりに、Arrays.asListメソッドを使用して同様の方法でListとして初期化することもできます。

public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");

それからあなたは(上記のように)することができます:

STRINGS.contains("the string you want to find");
32
Mark Rhodes

Arraysクラス を使用して、値のバイナリ検索を実行できます。配列がソートされていない場合は、同じクラスのソート関数を使用して配列をソートしてから検索してください。

25
Thomas Owens

ObStupidAnswer(ただし、ここにレッスンがあると思います)。

enum Values {
    AB, BC, CD, AE
}

try {
    Values.valueOf(s);
    return true;
} catch (IllegalArgumentException exc) {
    return false;
}
16

実際、Tom Hawtinが提案したようにHashSet <String>を使用すれば、ソートについて心配する必要はなく、処理速度は事前ソートされた配列でのバイナリ検索と同じですが、おそらくさらに高速です。

明らかに、それはあなたのコードがどのように設定されているかに依存しますが、私の立場からすると、順序は次のようになります。

未ソート 配列では、

  1. ハッシュセット
  2. asList
  3. ソート&バイナリ

ソート済み配列の場合

  1. ハッシュセット
  2. バイナリ
  3. asList

どちらにせよ、HashSetは勝利のために。

12
not

Googleコレクションライブラリをお持ちの場合は、ImmutableSetを使用してトムの回答を簡単にすることができます。

これは本当に提案された初期化から多くの雑然とを取り除きます。

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

1つの可能な解決策:

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

開発者はよくすること:

Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);

上記のコードは機能しますが、リストを最初にsetに変換する必要はありません。リストをセットに変換するには余分な時間がかかります。それは同じくらい簡単にすることができます:

Arrays.asList(arr).contains(targetValue);

または

   for(String s: arr){
        if(s.equals(targetValue))
            return true;
    }

return false;

最初のものは2番目のものより読みやすいです。

7
Xar E Ahmer

Java 8 に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);
6
Shineed Basheer

これを行うには、単純なループを使用するのが最も効率的な方法です。

boolean useLoop(String[] arr, String targetValue) {
    for(String s: arr){
        if(s.equals(targetValue))
            return true;
    }
    return false;
}

Programcreek の好意により

5
Ryan
  1. 限られた長さの配列のために( camickr によって与えられるように)以下を使用してください。特に長い配列(線形検索)の場合、これは繰り返しのチェックでは遅くなります。

     Arrays.asList(...).contains(...)
    
  2. 多数の要素を繰り返しチェックすることでパフォーマンスを向上させる

    • 配列は間違った構造です。TreeSetを使用して、それに各要素を追加します。それは要素をソートして高速のexist()メソッド(バイナリサーチ)を持ちます。

    • 要素がComparableを実装していて、それに応じてソートされたTreeSetが欲しい場合:

      ElementClass.compareTo()メソッドはElementClass.equals()と互換性がなければなりません: Triadsが戦闘に出ていないのでしょうか?(Java Setにアイテムがない) を参照してください

      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));
      
    • それ以外の場合は、独自の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);
      
    • 見返り:何らかの要素の存在を確認する:

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

これを試して:

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");
}
3
Mr.G

次のコードを使用してください(このコードのcontains()メソッドはArrayUtils.in()です)。

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

}

上記のコードからわかるように、他の場所でも使用されている他のユーティリティメソッドObjectUtils.equals()ArrayUtils.indexOf()があります。

3
Abhishek Oza

Arrays.asList() - > contains()メソッドを呼び出すことは常にうまくいきますが、配列の周りに軽量なリストラッパーを作成する必要がないので検索アルゴリズムがはるかに優れています。これが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.
}
2
WIll

大文字と小文字を区別したくない場合

Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
2
Akhil babu K

与えられたオブジェクトを配列で検索するかどうかにはArray.BinarySearch(array,obj)を使います。

例:

if (Array.BinarySearch(str, i) > -1)` → true --exists

false - 存在しません

2
Avenger

これをチェックして

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
    }
}
2
SubbaRao Boddu

最初はfalseに設定されているブール値を作成します。ループを実行して配列内のすべての値を調べ、調べている値と比較します。もしあなたがマッチしたら、ブール値をtrueに設定してループを止めます。それから真偽値が真であることを主張しなさい。

0
mandy1339