This week's giveaway is in the Android forum.
We're giving away four copies of Android Security Essentials Live Lessons and have Godfrey Nolan on-line!
See this thread for details.
The moose likes Java in General and the fly likes Sorting an array of objects Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Sorting an array of objects" Watch "Sorting an array of objects" New topic
Author

Sorting an array of objects

Malcolm Whitely
Greenhorn

Joined: Feb 06, 2003
Posts: 16
Hello,
I currently have an array made up of objects, with attributes 'word' and 'frequency'. After populating the array the user is asked if they would like the array to be displayed in alphabetic order (ie by word) or by decreasing frequency order (ie by frequency).
When I applied the Arrays.sort(object[]) method to my array I got the ClassCastException error, so I read through the API and it seemed to me like I needed to use the Comparable interface to be able to sort the array.
I've implemented 'Comparable' in the object class and defined a CompareTo method, but don't know where to go from there:
Here is my object class code:


and this is a method from my main class (note that words[] is already populated wuth unsorted data:

Any help would be greatly appreciated.
[ February 23, 2003: Message edited by: Malcolm Whitely ]
Avi Abrami
Ranch Hand

Joined: Oct 11, 2000
Posts: 1121

Hi Malcolm,
In my opinion, you need two "compareTo()" methods -- depending on whether you want to sort by frequency, or word. So you need some way to inform your class of which sort to use.
In any case, for the "compareTo()" method when sorting by 'word', may I suggest:

Of-course, the above is untested (and I haven't even tried to compile it), and incomplete, but, hopefully, it will help you to get started.
Hope this helps.
Good Luck,
Avi.
Maulin Vasavada
Ranch Hand

Joined: Nov 04, 2001
Posts: 1871
hi Malcolm,
i guess u can use Comparator Interface instead of Comparable as you have two kind of sorting possible on the set of objects...
here is a rough and non-tested code...
[code
class wordSort implements Comparator {
public int compare(Object o1, Object o2) {
WFreqRecord temp1 = (WFreqRecord)o1;
WFreqRecord temp2 = (WFreqRecord)o2;
return temp1.getWord().compareTo(temp2.getWord());
}
}

class freqSort implements Comparator {

public int compare(Object o1, Object o2) {
// similar conversion in temp1, temp2 objects

return temp1.getFreq() - temp2.getFreq();
}
}
class test {
WFreqRecord[] data = new WFreqRecord[] { // some data };

// sorting by words
Array.sort(data,new wordSort());

// sorting by freq
Array.sort(data,new freqSort());
}
[/code]
hope this helps..
regards
maulin...
Maulin Vasavada
Ranch Hand

Joined: Nov 04, 2001
Posts: 1871
of course u will customize to check for nulls and etc and put the sorting method calls in appropriate places...
regards
maulin.
Malcolm Whitely
Greenhorn

Joined: Feb 06, 2003
Posts: 16
Thank you for the replies.
Maulin, I tried the code you suggested and it compiles correctly. The only problem is that the sorting does not seem to be working properly.
My unsorted array looks like this (word/frequency):
this 2
is 3
a 3
test 2
and 1
sentence 2
to 2
see 1
if 1
the 1
code 1
works 1
properly 1
line 1
three 1
which 1
also 1
happens 1
be 1
When sorted by frequency, the result comes out as:
and 1
this 2
test 2
sentence 2
is 3
a 3
see 1
if 1
the 1
code 1
works 1
to 2
properly 1
line 1
three 1
which 1
also 1
happens 1
be 1
Sorting by word gives a different order, but like the frequency sort, the first two records appear to be sorted properly (ie "a" and "and" are the first two).
I'd be thankful for your help
Take care.
Malcolm
Ashish Mahajan
Ranch Hand

Joined: Feb 19, 2003
Posts: 77
Hi,
This should work :-
====================================
public class WFreqRecord
{
private String word;
private int freq;
public WFreqRecord(String str, int frequency)
{
word = str;
freq = frequency;
}
public String getWord()
{
return word;
}
public void setWord(String str)
{
word = str;
}
public int getFrequency()
{
return freq;
}
public void setFrequency(int frequency)
{
freq = frequency;
}
public String toString()
{
return getWord() + " " + getFrequency();
}
}
=======================================
public class Test
{
public static void main(String[] args)
{
WFreqRecord[] data = getData();
// sorting by words
Arrays.sort(data, new Comparator()
{
public int compare(Object o1, Object o2)
{
WFreqRecord temp1 = (WFreqRecord)o1;
WFreqRecord temp2 = (WFreqRecord)o2;
return temp1.getWord().compareTo(temp2.getWord());
}
});
System.out.println("Sorting by Words :-");
printArray(data);
data = getData();
// sorting by freq
Arrays.sort(data, new Comparator()
{
public int compare(Object o1, Object o2)
{
WFreqRecord temp1 = (WFreqRecord)o1;
WFreqRecord temp2 = (WFreqRecord)o2;
return temp1.getFrequency() - temp2.getFrequency();
}
});
System.out.println("Sorting by Freq :-");
printArray(data);
}
private static void printArray(Object[] arr)
{
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
System.out.println("------------------------");
}
protected static WFreqRecord[] getData()
{
return new WFreqRecord[]{
new WFreqRecord("this", 2),
new WFreqRecord("is", 3),
new WFreqRecord("a", 3),
new WFreqRecord("test", 2),
new WFreqRecord("and", 1),
new WFreqRecord("sentence", 2),
new WFreqRecord("to", 2),
new WFreqRecord("see", 1),
new WFreqRecord("if", 1),
new WFreqRecord("the", 1),
new WFreqRecord("code", 1),
new WFreqRecord("works", 1),
new WFreqRecord("properly", 1),
new WFreqRecord("line", 1),
new WFreqRecord("three", 1),
new WFreqRecord("which", 1),
new WFreqRecord("also", 1),
new WFreqRecord("happens", 1),
new WFreqRecord("be", 1)
};
}
}


The best teams have no specialists, only general contributors with special skills
Malcolm Whitely
Greenhorn

Joined: Feb 06, 2003
Posts: 16
Thanks for the reply Ashish. Your code works great, but I am unable to see how different it is to the code posted by Maulin.
I've spent a few hours so far comparing my code with yours and am still frustrated. Could it be that my array has a size of 100 whereas only about 20 elements are used?
Thanks for your time.
Maulin Vasavada
Ranch Hand

Joined: Nov 04, 2001
Posts: 1871
hi Malcolm,
yes you are right. the code Ashish posted and the code i gave are "same" w.r.t to compare() methods...
it should work fine...
can you post your code as it is. i would like to have a look at it...
btw, Ashish's code work for all 100 elements in your array , right?
there has to be some difference in what you wrote interpreted from my algorithm and what Ashish wrote...i would like to make out that..
regards
maulin.
Malcolm Whitely
Greenhorn

Joined: Feb 06, 2003
Posts: 16
Hi there Maulin,
I did a quick test and resized my array to 19 (number of actual used elemented) and the sort worked fine. However, when there are null elements in the array, neither algorithm works properly. I hope there is a way around this.
Maulin, do you mind if I email you my code since it is quite long and there are a fair number of interfaces in it.
Thanks again
Ashish Mahajan
Ranch Hand

Joined: Feb 19, 2003
Posts: 77
Hi Malcom,
The reason both algo not working when u pass null objects is simple. Arrays while sorting will delegate sorting's comparate to decision to the passed in comparator. Well in both comparators we are comparing by callinmg methods on the passed in instances. Naturally if the obj is null then it will throw NullPointerException.
I have seen that few people r trying to check for null in such cases. So let me say few things :-
In such situations it is best not to catch exceptions. One can simply check for the instances for null and then before performing any operation on the obj, simply return if its null. But trust me this is bad programming practice. The reason is - what null indicates, where to place this null value, will this null value will give something meaningful. Java is fundamentally strong type checking language and wiil eliminate the bad code right at the time of compilation. However not everything can be checked at the time of compilatoion.
In above case i'll rather say the method which builds the data is responsible for checking the values against null and if it is then simply don't put it in collection. If we keep the member variable private then there is a single gate to alter the state of that member thru setXXX method. The developer should check for valid values before setting generating exceptions at right time so that it is always guaranteed that the member variable is a valid one.
Do u know when to toss exception and when to throw error is also very interesting to study.
Best Of Luck
Jamie Robertson
Ranch Hand

Joined: Jul 09, 2001
Posts: 1879

I've always believed that if a class has different ordering needs, then the compareTo method should be the most natural ordering ( like a default ordering ) and any other orderings should be encapsulated by the class:


and this is a method from my main class (note that words[] is already populated wuth unsorted data:

to return the list sorted by words, just use
Arrays.sort( recordsByFreq, WFreqRecords.WORD_ORDER );
Jamie
Malcolm Whitely
Greenhorn

Joined: Feb 06, 2003
Posts: 16
Thanks Jamie and Ashish for your replies. Ashish, unfortunately, I am guilty of practicing what you mentioned as bad programming practice since I break my loop by checking for a Null reference. At present it seems to be the easiest way to get around determining when to stop looping
I have since solved the issue with the sorting by storing my frequency data in a hashmap. I then create an array of size hashmap and populate it with the hashmap's keys.
Thanks to everyone for their help.
PS. No, I don't know when to toss exceptions and throw errors. Mind explaining it to me
Ashish Mahajan
Ranch Hand

Joined: Feb 19, 2003
Posts: 77
Hi Jamie/Malcolm,
Thanx Jamie very much.
I added one more to the list of Design Patterns.
Thanx.
Malcolm, study Java's source code thoroughly that will make it clear about exceptions.
---------
Anyone who has never made a mistake has never tried anything new - Albert Einstein
Jamie Robertson
Ranch Hand

Joined: Jul 09, 2001
Posts: 1879

I was going to mention this earlier, but how are you using a HashMap Collection when you haven't overridden the equals() and hashCode() methods? I will not work efficiently or correctly for that matter if you don't. See this for more information on overriding these methods.
Jamie
Jamie Robertson
Ranch Hand

Joined: Jul 09, 2001
Posts: 1879

how do you ensure ordering using the HashMap?
From the API's:
" The order of a map is defined as the order in which the iterators on the map's collection views return their elements. Some map implementations, like the TreeMap class, make specific guarantees as to their order; others, like the HashMap class, do not."
Ashish Mahajan
Ranch Hand

Joined: Feb 19, 2003
Posts: 77
Hi Jamie,
We haven't used HashMap in our example. Actually i think u mean using TreeSet, don't U??? I know about the collections stuff. I thought Malcom's requirement is to get the data in Object[] array and then sort it otherwise TreeSet is best to go. But the article u provided is really helpful to understand hashCode() and equals(). I didn't know that. Well am not old nor new hence, u see, am in Java(intermediate) forum.
Thank U very much.
BTW just wanna say about me. Am always ready to learn so if anybody wanna chime in, they can. the goal is to study the funda collectively fundamentally.
Maulin Vasavada
Ranch Hand

Joined: Nov 04, 2001
Posts: 1871
hi Malcolm,
sorry i'm out of touch for couple of days i will look thru all these posts.
regards
maulin
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Sorting an array of objects
 
Similar Threads
Getting grades into a gradebook
compareTo method
compareTo and Arrays.sort
Binary search???
Sorting