私はString[]
そのような値で:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
与えられたString s
かどうかをテストする良い方法はありますか?VALUES
含むs
?
Arrays.asList(yourArray).contains(yourValue)
警告:これはプリミティブの配列に対しては機能しません(コメントを参照)。
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
の配列かどうかを確認するint
、double
またはlong
値の使用が含まれていますIntStream
、DoubleStream
またはLongStream
それぞれ。
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
ArrayList
、 だがしかしjava.util.ArrayList
ご想像のとおり、返される実際のクラスは次のとおりです。java.util.Arrays.ArrayList<E>
以下のように定義されます。public class java.util.Arrays {private static class ArrayList<E> ... {}}
。 - TWiStErRob
まず始めにコードをクリアします。我々は(修正)を持っています:
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
- それは公にされることさえ可能である。
「文字列が与えられた場合、VALUESにsが含まれているかどうかをテストする良い方法はありますか?」
VALUES.contains(s)
O(1)
Arrays.asList
)? - Basil BourqueTreeSet
だろうO(log n)
。HashSet
sは、バケット内の要素の平均数がほぼ一定になるように調整されます。少なくとも2 ^ 30までの配列に対して。 big-O分析で無視されるハードウェアキャッシュなどから影響が出る可能性があります。ハッシュ関数が効果的に機能していると仮定します。 - Tom Hawtin - tackline
あなたが使用することができますArrayUtils.contains
からApache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
このメソッドはfalse
渡された配列がnull
。
すべての種類のプリミティブ配列に利用可能なメソッドもあります。
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
単純に手作業で実装することを提案した人がいないのは驚きです。
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
conditionはメソッド内では定数であり、メソッド呼び出し中は常に同じブール値に評価されます。そう入力ならarray
が大きい場合、この条件を一度だけ評価するほうが効率的です。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;
}
Collection.contains(Object)
- Steve KuoArrays
そしてArrayList
これは、使用しているバージョンよりも必ずしも速くはないことがわかりました。Arrays.asList(...).contains(...)
。作成のオーバーヘッドArrayList
非常に小さいです、そしてArrayList.contains()
上に示したもの(JDK 7)よりもスマートなループを使用します(実際には2つの異なるループを使用します)。 - Axel
配列がソートされていない場合は、すべてを反復処理し、それぞれに対してequalsを呼び出す必要があります。
配列がソートされている場合は、バイナリ検索を実行できます。配列クラス。
一般的に言って、もしあなたがたくさんのメンバーシップチェックをするつもりなら、あなたは配列ではなくセットにすべてを保存したいかもしれません。
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
(a >= 0)
正しかった、ただチェックするドキュメント「これは、キーが見つかった場合に限り、戻り値が> = 0になることを保証することに注意してください。」 - Yoory N.
その価値のために、私はスピードに関する3つの提案を比較するテストを実行しました。ランダムな整数を生成し、それらを文字列に変換して配列に追加しました。私はそれから、可能な限り高い数/文字列を探しました。これはasList()のための最悪のシナリオのシナリオです。
10Kの配列サイズを使用すると、結果は次のようになります。
Sort & Search : 15 Binary Search : 0 asList.contains : 0
100Kアレイを使用すると、結果は次のようになります。
Sort & Search : 156 Binary Search : 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));
}
}
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);
}
クイック配列初期化構文を使用する代わりに、Arrays.asListメソッドを使用して同様の方法で直接Listとして初期化することもできます。
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
それからあなたは(上記のように)することができます:STRINGS.contains("the string you want to find");
あなたが使用することができます配列クラス値のバイナリ検索を実行します。配列がソートされていない場合は、同じクラスのソート関数を使用して配列をソートしてから検索する必要があります。
ObStupidAnswer(ただし、ここにレッスンがあると思います)。
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
実際、Tom Hawtinがソートについて心配する必要はないと提案したようにHashSetを使用すれば、速度は事前ソートされた配列に対するBinary Searchと同じ、おそらくもっと速いです。
それはすべてあなたのコードがどのように設定されているかにかかっているのは明らかですが、私の立場からすると、順番は次のようになります。
UNsorted配列では、
ソート済み配列の場合
どちらにしても、HashSet ftw
Googleコレクションライブラリをお持ちの場合は、ImmutableSet(http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)を使用すると、Tomの回答を非常に簡単にすることができます。
これは本当に提案された初期化から多くの雑然とを取り除きます
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
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");
}
}
}
開発者はよくすること:
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番目のものより読みやすいです。
にJava 8Streamsを使用してください。
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);
これを行うには、単純なループを使用するのが最も効率的な方法です。
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
への礼儀プログラムクリーク
限られた長さの配列の場合は、次のようにしてください(で与えられます)。camickr)これは繰り返しのチェック、特に長い配列(線形検索)では遅くなります。
Arrays.asList(...).contains(...)
多数の要素を繰り返しチェックすることでパフォーマンスを向上させる
配列は間違った構造です。使うTreeSet
それに各要素を追加します。それは要素をソートして速いexist()
メソッド(二分探索)。
要素が実装している場合Comparable
&あなたが欲しいTreeSet
それに従ってソート:
ElementClass.compareTo()
メソッドは以下と互換性がなければなりませんElementClass.equals()
: 見るトライアドは戦うために現れていませんか? (Javaセットにアイテムがありません)
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);
TreeSet
?HashSet
より速く(O(1))、順序付けは不要です。 - Sean Owen
これをチェックして
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
にとってすべての一致しないアイテム(その配列で「AB」を探している場合、3つの値が一致しないため、3回検索されます)。 - Dukeling
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.
}
Arrays.asList
O(n)ではありません。これは単なる軽量のラッパーです。実装を見てください。 - Patrick Parker
つかいますArray.BinarySearch(array,obj)
与えられたオブジェクトを配列で見つけるかどうか。
例:
if (Array.BinarySearch(str, i) > -1)
- > true --exists
false - 存在しません
これを試して:
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");
}
この議論に参加するのは非常に遅れていますが、この問題を解決するための私のアプローチは、数年前に直面したときには、ここに掲載した他の答えとは少し異なっていました。だれでもそれが役に立つと思うならば、ここで、(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()
、それは他の場所でも使われていました。
大文字と小文字を区別したくない場合
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
最初はfalseに設定されているブール値を作成します。ループを実行して配列内のすべての値を確認し、確認している値と比較します。あなたがマッチを得たならば、真偽値をtrueにセットして、そしてループを止めなさい。その後、ブール値がtrueであることを表明します。