Custom Sorting with IComparer and IComparable
I recently developed an application using VB.NET to preview movies located on my media server. I decided to develop this application when I got sick of opening the movie folder, clicking the backdrop image to see if I remembered the movie and then opening the XML file to view the meta data.
You may ask why I have my movies stored within folders anyway but the answer is simple. This is the format media browser (a windows media centre plug-in) prefers them so it can store relevant meta data and backdrop images for each movie. Unfortunately unless you use window media centre on every computer the movies become a real pain to view manually through explorer.
Once I had built the application which was rather straight forward, with simply a combination of opening a xml file and reading the required data and resizing the image to be displayed for each movie I then wanted some custom sorts. I started off creating my own sorts which worked with a combination of loops and object swapping but when used with over 300 movies the process got quite slow (4 or 5 seconds).This is where IComparer and IComparable comes in.
First we will talk about IComparable, implementing this interface allows us to use our own CompareTo method when we are sorting our objects. For my custom Media objects I wanted the default sort to be the creation date of the file. The code below shows my own CompareTo method and the comparison of the two dates. It must return an integer value. If value one is less than value two then it must return less than 0, if the two values are the same then return 0 and if value two is less than value one then it must return a value greater than 0.
Public Function CompareTo(ByVal obj As Object) As Integer Implements IComparable.CompareTo If Not TypeOf obj Is Media Then Throw New Exception("Object is not of type Media") End If Return Date.Compare(obj.getCreationDate, Me.getCreationDate) End Function
This method is now used by the framework if we try to use the Array.Sort method on any array or arraylist containing a collection of our Media objects.
Ok so now we have the default sort for my Media objects in place it's time to implement a few more sorts using IComparer. First we create an inner class which will implement IComparer and then we will create our own ICompare method which will implement IComparer.Compare.
Private Class SortByNameAscending Implements IComparer Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare Dim m1 As Media = CType(x, Media) Dim m2 As Media = CType(y, Media) Dim m1Name As String = m1.getFolderName.ToLower Dim m2Name As String = m2.getFolderName.ToLower If m1Name > m2Name Then Return 1 End If If m1Name < m2Name Then Return -1 Else Return 0 End If End Function End Class
The final step is to create a shared function within our main class which returns the inner class as an IComparer. This can then be used when calling Array.Sort(). Here is the shared function and an example of how to call Array.Sort().
Public Shared Function SortByNameAscendingOrder() As IComparer Return CType(New SortByNameAscending, IComparer) End Function
mediaData is an array list of Media objects. The below code will sort the list using the SortByNameAscendingOrder class Compare method.
IComparer and IComparable are invaluable classes and improved the performance of my application ten fold. They are simple to use and worth investigating. If anyone has any problems please leave a comment and I will try my best to help.
Also if anyone is interested in the source code to the movie file viewer please let me know and I will release it.