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.
mediaData.Sort(Media.SortByNameAscendingOrder)
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.
Add new comment