2

I am using a bubble sort to sort two different objects I have within a list. Right now it seems to be putting the Knowledge articles before the Events, and furthermore the Date is not sorting properly. Can anyone tell from my code why it may be prioriting knowledge articles, and why its not sorted by date properly?

        //Sort the lists ----> listEw listAw sort by date and put into following list

    List<ListWrapper> listOfWrappers = new List<ListWrapper>();
        listOfWrappers.addAll(listEw);
        listOfWrappers.addAll(listAw);
        System.debug(listofWrappers);

    listOfWrappers= bubbleSortMethod(listOfWrappers);
        System.debug('Sorted List' + listOfWrappers);
    return listOfWrappers; 

}
    public static List<ListWrapper> bubbleSortMethod(List<ListWrapper> values){
    integer iterationsize = values.size();
    ListWrapper temp = null;

    for(integer i=0; i < iterationsize; i++){
        for(integer j=1; j < (iterationsize-i); j++){
            DateTime value1 = (values[j].article != null) ? values[j].article.CreatedDate : values[j].event.CreatedDate; //Checks to see if it's an article or event and then applies the correct date to the value
            DateTime value2 = (values[j-1].article != null) ? values[j-1].article.CreatedDate : values[j-1].event.CreatedDate;//Checks to see if it's an article or event and then applies the correct date to the value
            if(value2 > value1){
                //swap the elements!
                temp = values[j-1];
                values[j-1] = values[j];
                values[j] = temp;
            }
        }
    }

    System.debug('values ' + values);
    return values;
}

}

UPDATE: I am implementing JCD's comparable code but have run into the following error on a different line of code. Code shown below

        List<ListWrapper> listAw = new List<ListWrapper>();
    for(Knowledge__kav kA : articles){
        ListWrapper aW = new ListWrapper();
        aW.article = kA;
        listAw.add(aW);
        System.debug('The Article List' + listAw);
    }

The line ListWrapper aW = new ListWrapper(); now gets "constructor not defined: [WhatsNewController.ListWrapper].()

  • For others' reference, this seems to be a continuation of salesforce.stackexchange.com/questions/277812/… – Derek F Sep 12 at 20:39
  • Derek F man welcome back! Yeah I wasn't sure whether to link them since the first article refers to a comparable sort and this is a bubble sort. Either way let me know if you can see what might be going on. Thanks! – Trace Sep 12 at 20:41
  • 1
    I'd still recommend implementing comparable, but I won't have the time to write up an answer tonight. I'll keep an eye on this one and see if it still needs some love tomorrow. – Derek F Sep 12 at 20:45
  • Thanks I appreciate it. – Trace Sep 12 at 20:49
  • 2
    Without having read the other linked question, is there a reason you're rolling your own bubble sort instead of implementing Comparable? Just feel like testing your Apex mettle, perhaps? – JCD Sep 12 at 20:51
2

While this may not be exactly what you asked for, I'd probably recommend implementing Comparable to avoid the very problem you're having - spinning your wheels wondering if it's a bug in your sorting implementation or if the problem lies elsewhere. It may perform slightly worse over large collections of objects, but it will allow you to isolate issues and extend the pattern if necessary down the road.

I'm assuming your wrapper class might look something like this (if you're using the standard Event object or Knowledge Article records, please excuse my custom object replacements):

public class ListWrapper {
    public Article__c article   {public get; private set;}
    public Event__c event       {public get; private set;}

    public ListWrapper(Article__c article) {
        this.article = article;
    }
    public ListWrapper(Event__c event) {
        this.event = event;
    }
}

This wrapper class is pretty "dumb", but with just a few tweaks you can add basic sorting:

public class ListWrapper implements Comparable {
    private DateTime sortDate;
    public Article__c article   {public get; private set;}
    public Event__c event       {public get; private set;}

    public ListWrapper(Article__c article) {
        this.sortDate = article.CreatedDate;
        this.article = article;
    }
    public ListWrapper(Event__c event) {
        this.sortDate = event.CreatedDate;
        this.event = event;
    }

    public Integer compareTo(Object other) {
        ListWrapper o = (ListWrapper)other;
        if ( this.sortDate == o.sortDate ) {
            return 0;
        }
        // in this case we probably don't have to worry about CreatedDate = null...but ideally you'd want to handle that
        return (this.sortDate < o.sortDate) ? -1 : 1;
    }
}

Then your sorting really just becomes:

List<ListWrapper> listOfWrappers = new List<ListWrapper>();
listOfWrappers.addAll(listEw);
listOfWrappers.addAll(listAw);
System.debug('unsorted: ' + listOfWrappers);
listOfWrappers.sort();  // let the magic of Comparable do the work
System.debug('sorted: ' + listOfWrappers);

As I said, you can easily extend this and get as fancy as you want. You could add support for generic SObjects, or, for example, you could add behavior similar to SOQL's asc/desc and NULLS FIRST/NULLS LAST keywords:

// static flags, since inner classes can't contain static vars, and to make sure every instance is working with the same rules
public static Boolean sortDesc = false;         // set to true for descending sorting
public static Boolean sortNullsFirst = false;   // set to true for nulls first (if there are any)

public class ListWrapper implements Comparable {
    private DateTime sortDate;
    public Article__c article   {public get; private set;}
    public Event__c event       {public get; private set;}

    public ListWrapper(Article__c article) {
        this.sortDate = article.CreatedDate;
        this.article = article;
    }
    public ListWrapper(Event__c event) {
        this.sortDate = event.CreatedDate;
        this.event = event;
    }

    public Integer compareTo(Object other) {
        ListWrapper o = (ListWrapper)other;
        if ( this.sortDate == o.sortDate ) {
            return 0;
        }
        if ( this.sortDate == null ) {
            return (sortNullsFirst ? -1 : 1);
        }
        if ( o.sortDate == null ) {
            return (sortNullsFirst ? 1 : -1);
        }
        return (sortDesc? -1 : 1)*((this.sortDate < o.sortDate) ? -1 : 1);
    }
}

Check out the Salesforce Dev Guide for more information on the Comparable Interface.

  • Thank you. I implemented this code as you have it but switching out article__c and event__c for their proper object names. I am now getting "Constructor not defined: [WhatsNewController.ListWrapper].() for the following line of code List<ListWrapper> listEw = new List<ListWrapper>(); for(Community_Event__c cE : events){ ListWrapper eW = new ListWrapper(); eW.event = cE; listEw.add(eW); System.debug('the event list' + listEw); specifically ` ListWrapper eW = new ListWrapper();` – Trace Sep 13 at 15:11
  • In my sample code there isn't an empty constructor in the ListWrapper class - rather than creating a new instance, setting event explicitly and then adding it to your list with these three lines ListWrapper eW = new ListWrapper(); eW.event = cE; listEw.add(eW);, you can use a constructor and do it in a single line, like so: listEw.add(new ListWrapper(cE));. Besides, the way you're doing it won't take advantage of the sortDate member, which is critical for the sorting functionality. – JCD Sep 13 at 15:43
  • Awesome thank you so much! – Trace Sep 13 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.