• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Sorting an array of objects

 
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Ranch Hand
Posts: 1143
1
Eclipse IDE Oracle Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 16
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 77
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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)
};
}
}
 
Malcolm Whitely
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 16
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 77
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 1879
MySQL Database Suse
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 16
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 77
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1879
MySQL Database Suse
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1879
MySQL Database Suse
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 77
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 1873
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hi Malcolm,
sorry i'm out of touch for couple of days i will look thru all these posts.
regards
maulin
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic