Long way around it, but you can use a for loop: "for (String s : VALUES) if (s.equals("MYVALUE")) return true;
–
ZackJul 15 '09 at 0:51

Yeah, I was almost embarrassed to ask the question, but at the same time was surprised that it hadn't been asked. It's one of those APIs that I just haven't been exposed to...
–
Mike SicklerJul 15 '09 at 1:20

14

Why are people still upvoting this answer (now 75)? Its 2 years old and a very simple answer. All I did was point someone to an API method. I don't think any answer is so ammazing that it deserves this nunmber of upvotes.
–
camickrJun 24 '11 at 15:29

@camickr--I have a nearly identical situation with this one: stackoverflow.com/a/223929/12943 It just keeps getting votes yet was just a copy/paste from sun's documentation. I guess score is based on how much help you provided and not how much effort you put into it--and mostly how fast you post it! Maybe we've stumbled onto John Skeet's secret! Well good answer, +1 for you.
–
Bill KApr 29 '13 at 6:50

23 Answers
23

I am somewhat curious as to the performance of this versus the searching functions in the Arrays class versus iterating over an array and using an equals() function or == for primitives.
–
Thomas OwensJul 15 '09 at 0:06

103

You don't lose much, as asList() returns an ArrayList which has an array at its heart. The constructor will just change a reference so that's not much work to be done there. And contains()/indexOf() will iterate and use equals(). For primitives you should be better off coding it yourself, though. For Strings or other classes, the difference will not be noticeable.
–
JoeyJul 15 '09 at 0:09

11

Odd, NetBeans claims that 'Arrays.asList(holidays)' for an 'int[] holidays' returns a 'list<int[]>', and not a 'list<int>'. It just contains one single element. Meaning the Contains doesn't work since it just has one element; the int array.
–
NyergudsNov 13 '10 at 13:15

32

Nyerguds: indeed, this does not work for primitives. In java primitive types can't be generic. asList is declared as <T> List<T> asList(T...). When you pass an int[] into it, the compiler infers T=int[] because it can't infer T=int, because primitives can't be generic.
–
CromTheDestroyerJun 14 '11 at 16:51

9

@Joey just a side note, it's an ArrayList, but not java.util.ArrayList as you expect, the real class returned is: java.util.Arrays.ArrayList<E> defined as: public class java.util.Arrays {private static class ArrayList<E> ... {}}.
–
TWiStErRobOct 17 '12 at 9:16

Except it's O(N) to create the collection in the first place :)
–
Drew NoakesApr 25 '11 at 6:54

22

If it's static, it's probably going to be used quite a few times. So, the time consumed to initialise the set has good chances of being quite small compared to the cost of a lot of linear searches.
–
Xr.Oct 12 '11 at 19:39

Creating then the collection is going to be dominated by code loading time (which is technically O(n) but practically constant).
–
Tom Hawtin - tacklineMar 7 '12 at 13:23

@TomHawtin-tackline Why do you say "in particular here we want a set"? What is the advantage of a Set (HashSet) in this case? Why is a "reference array" bad (by "reference array" do you mean an ArrayList backed by an array as generated by a call to Arrays.asList)?
–
Basil BourqueAug 29 '14 at 5:04

1

@nmr A TreeSet would be O(log n). HashSets are scaled such that the mean number of elements in a bucket is roughly constant. At least for arrays up to 2^30. There may be affects from, say, hardware caches which the big-O analysis ignores. Also assumes the hash function is working effectively.
–
Tom Hawtin - tacklineSep 9 '14 at 23:51

The v != null condition is constant inside the method, it always evaluates to the same boolean value during the method call. So if the input array is big, it is more efficient to evaluate this condition only once and we can use a simplified/faster condition inside the for loop based on the result. The improved contains() method:

@Phoexo This solution is obviously faster because the accepted answer wraps the array into a list, and calls the contains() method on that list while my solution basically does what contains() only would do.
–
iczaOct 10 '12 at 11:25

1

e == v || v != null && v.equals( e ) --- The first part of the OR statement compares e and v. The second part does the same (after checking v isn't null). Why would you have such an implementation instead of just (e==v). Could you explain this to me?
–
Alastor MoodyJan 14 '13 at 16:38

9

@AlastorMoody e==v does a reference equality check which is very fast. If the same object (same by reference) is in the array, it will be found faster. If it is not the same instance, it still might be the same as claimed by the equals() method, this is what is checked if references are not the same.
–
iczaJan 15 '13 at 8:39

8

Why isn't this function part of Java? No wonder people say Java is bloated... look at all the answers above this that use a bunch of libraries when all you need is a for loop. Kids these days!
–
phreakheadApr 2 '13 at 19:30

7

@icza If you look at the source of Arrays and ArrayList it turns out that this isn't necessarily faster than the version using Arrays.asList(...).contains(...). Overhead of creating an ArrayList is extremely small, and ArrayList.contains() uses a smarter loop (actually it uses two different loops) than the one shown above (JDK 7).
–
AxelFeb 11 '14 at 7:41

@max4ever Sometimes you already have this library included (for other reasons) and it is a perfectly valid answer. I was looking for this and I already depend on Apache Commons Lang. Thanks for this answer.
–
GuiSimApr 22 '14 at 19:30

Or you could just copy the method (and depedencies if there are any).
–
BuffaloMar 9 at 11:59

Also, like I said in my answer, if you use the Arrays class, you can sort the array then perform the binary search on the newly sorted array.
–
Thomas OwensJul 15 '09 at 0:10

1

@Thomas: I agree. Or you can just add everything into a TreeSet; same complexity. I would use the Arrays if it doesn't change (maybe save a little bit of memory locality since the references are located contiguously though the strings aren't). I would use the set if this would change over time.
–
UriJul 15 '09 at 0:14

For what its worth I ran a test comparing the 3 suggestions for speed. I generated random integers, converted them to a String and added them to an array. I then searched for the highest possible number/string, which would be a worst case scenario for the asList().contains().

When using a 10K array size the results where:

Sort & Search : 15
Binary Search : 0
asList.contains : 0

When using a 100K array the results where:

Sort & Search : 156
Binary Search : 0
asList.contains : 32

So if the array is created in sorted order the binary search is the fastest, otherwise the asList().contains would be the way to go. If you have many searches, then it may be worthwhile to sort the array so you can use the binary search. It all depends on your application.

I would think those are the results most people would expect. Here is the test code:

I don't understand this code. You sort the array 'strings' and use the same (sorted) array in both calls to binarySearch. How can that show anything except HotSpot runtime optimization? The same with the asList.contains call. You create a list from the sorted array and then does contains on it with the highest value. Of course it's going to take time. What is the meaning of this test? Not to mention being an improperly written microbenchmark
–
ErikMay 30 '13 at 9:16

Also, since binary search can only be applied to a sorted set, sort and search is the only possible way to use binary search.
–
ErikMay 30 '13 at 9:18

Sorting may have already been done for a number of other reasons, e.g., it could be sorted on init and never changed. There's use in testing search time on its own. Where this falls down however is in being a less than stellar example of microbenchmarking. Microbenchmarks are notoriously difficult to get right in Java and should for example include executing the test code enough to get hotspot optimisation before running the actual test, let alone running the actual test code more than ONCE with a timer. Example pitfalls
–
Thor84noOct 24 '13 at 12:25

4

This test is flawed as it runs all 3 tests in the same JVM instance. The later tests could benefit from the earlier ones warming up the cache, JIT, etc
–
Steve KuoJan 11 '14 at 0:39

You can use the sort functions in the same class to accomplish that...I should add that to my answer.
–
Thomas OwensJul 15 '09 at 0:06

1

Will probably cost more than the asList().contains() approach, then, I think. Unless you need to do that check very often (but if it's just a static list of values that can be sorted to begin with, to be fair).
–
JoeyJul 15 '09 at 0:10

True. There are a lot of variables as to which would be the most effective. It's good to have options though.
–
Thomas OwensJul 15 '09 at 0:13

To also add, anyMatch JavaDoc states that it "...May not evaluate the predicate on all elements if not necessary for determining the result.", so it may not need to continue processing after finding a match.
–
Mike KobitDec 15 '14 at 17:21

If you have the google collections library, Tom's answer can be simplified a lot by using ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)

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

I am very late to join this discussion, but since my approach in solving this problem, when I faced it a few years ago, was a bit different than the other answers already posted here, I am posting that solution I used at that time, over here, in case anyone finds it usefull: (The contains() method is ArrayUtils.in() in this code.)

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.
–
msrd0Nov 11 '14 at 15:53

No, because I'm suggesting he can use that library. Often, you simply aren't aware a library you already use has functionality you need.
–
Mr. BoyNov 12 '14 at 9:35