views:

80

answers:

4

Hi,

Is it possible to search an array of objects in Java by a private attribute with the Array.binarySearch method? I was thinking there must be something similar to the sorting technique, where you create a class that implements Comparator and pass this in to Array.sort, but I can't seem to find anything (maybe there is something where instead of the compareTo method you just return the attribute used in the search)??

To be clear I have an array of anonymous Station objects, and this is passed to another class where I want to search the array for the name of the stations, which can be returned via a getName().

Any help would be much appreciated!

+2  A: 

Yes, there's an overload that takes a comparator. Remember that you can only use binarySearch if the array is already sorted.

Matthew Flaschen
+2  A: 

Yes - in fact it uses Comparator, which you specified in your answer!

If you have a look over the implementations of the binarySearch method in the API, you come across binarySearch(T[] a, T key, Comparator c) which:

Searches the specified array for the specified object using the binary search algorithm.

You can implement the Comparator however you like, and so can use it to compare the private attributes alluded to in your question.

Edit responding to comment: The T is a generic parameter, meaning it can be anything, so long as it's the same in every position it appears. In this case, it means that the first parameter must be an array of the second parameter's type. Or in other words, if you're sorting an array of Ts (Stations in your case) then you need to pass in an instance of that class (Station here) to act as the object to compare against. This key argument will always be passed in as one of the arguments to the comparator's compare method.

So I suspect in your case you were passing in a String representing the station name; you should instead pass in an instance of Station which has the appropriate name.

Andrzej Doyle
Hey thanks for you answers, I did look into this but was confused...I passed in the array, a string and the comparator I used for the sort I mentioned, but get this error:The method binarySearch(T[], T, Comparator<? super T>) in the type Arrays is not applicable for the arguments (Station[], String, StationCompare)Also I'm obviously missing something if I'm just using the same comparator, but 'comparator' only has two methods, compare and equals, so not sure what to do. I'm new to java - I guess the T is just a parent object? Sorry, there's lots of questions there...
PickledFillx
The T is a generic wildcard; see my edit for more info.
Andrzej Doyle
Thanks for you help and clearing this up for me, much appreciated!
PickledFillx
A: 

If the array of stations is not already sorted by the station names, it makes no sense sorting and searching for every query. It is faster to do a linear search in this case. However, if you can sort the array and then perform multiple binary searches, it is worthwhile. Implement a comparator such as the following, and use it for both sorting (Arrays.sort(..)) and searching (Arrays.binarySearch(..)):

private class StationNameComparator implements Comparator<Station> {
    public int compare(Station s1, Station s2) {
        return s1.getName().compareTo(s2.getName());
    }
}

Note that I assume that the names are non-null and unique.

Eyal Schneider
Hi, Thanks, please see my comments on one of the answers above, and yes they are already sorted (this was required for another purpose). I did pass this comparator in which worked for the sort, but there's an error with the search... probably something fundamental...
PickledFillx
@Pickles: you passed wrong arguments. The search method expects the array, the item, and then the comparator. The item must be of type Station, since this is the type of the array's items. Therefore, you must use a dummy station object with the required name every time you search.
Eyal Schneider
hey thanks for you help, that's what I eventually did but thought it was the wrong way to do it, probably should have refreshed this page a few minutes ago!
PickledFillx
A: 

Thanks, eventually got it working using

Arrays.binarySearch(allStations,new Station("nameofstationhere"),new StationCompare())

which is probably a bad way as I'm creating a new Station object for comparison... but it works and not sure how to do it using just the string...

PickledFillx
If creating many instances bothers you, you can use the same instance of the comparator for all searches (since it is stateless). Also, Assuming that all searches run in the same thread, you can reuse the same temporary Station object, and change its name field before searches. Anyway, I wouldn't be concerned about excessive object creation, unless it proves to be the source of some performance problem.
Eyal Schneider
Yeah good point... it's not really the object creation that's annoys me, I was just thinking it was a bit strange that you have to create an object this way (for example with a larger object you may have to pass in a number of null parameters and what if the creation of an object caused some other unwanted behaviour). It would be nice if you could just pass in any type of object to the search method and overload the comparator as required, but hey, it beats doing everything manually so I'm not complaining! Thanks again for your comments.
PickledFillx