TripVoltage
TripVoltage

Reputation: 341

Multiple sort in java

ArrayList data example: BJM 300 AC4507 TOM_JONES, BDM 290 DC4058 ALAN_FIELD, ADG 350 BA3240 JON_THORN

I need to sort the arraylist above into ascending sequence of the third column within the second column within the first column?

I tried nesting the loops as follows but it's not working! What am I doing wrong??

    public static ArrayList sortLoad1(ArrayList<TeachingLoad> loads){
    String s1, s2;
    TeachingLoad temp;                                   //Some local variables
    for(int i = 0 ; i < loads.size(); i++){              //Loop throuth 
        for(int j = loads.size()-1; j>i  ;j--){          //Loop through 
            s1 = loads.get(j-1).getSchoolCode();        //Extract 1st
            s2 = loads.get(j).getSchoolCode();          //Extract 2nd
                if(i+1<loads.size()&&s1.compareTo(s2)>-1){  //Compare them lexicographically
                    temp = loads.get(j-1);
                    //If s1 follows s2 then switch both
                    loads.set(j-1, loads.get(j));
                    loads.set(j, temp);
                }
                else{
                    for(int k = 0 ; k < loads.size(); k++){            
                        for(int l = loads.size()-1; l>i  ;l--){     
                            s1 = loads.get(l-1).getDepartmentNumber();
                            s2 = loads.get(l).getDepartmentNumber();
                            if(k+1<loads.size()&&s1.compareTo(s2)>-1){
                                temp = loads.get(l-1);
                                loads.set(l-1, loads.get(l));
                                loads.set(l, temp);
                            }
                            else{
                                for(int m = 0 ; m < loads.size(); m++){         
                                    for(int n = loads.size()-1; n>i  ;n--){         
                                        s1 = loads.get(n-1).getLecturerID();
                                        s2 = loads.get(n).getLecturerID();
                                        if(m+1<loads.size()&&s1.compareTo(s2)>-1){
                                            temp = loads.get(n-1);
                                            loads.set(n-1, loads.get(n));
                                            loads.set(n, temp);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
        }//end loop
    }//end loop
    return loads;
} 

I know I can use a Comparator to do this, but I don't want to.

Any help welcome?

Many thanks TeachingLoad held in arraylist is:

    public TeachingLoad(String schoolCode, String departmentNumber, 
        String lecturerID, String lecturerName, 
        String moduleNo, String creditHours, String classSize) {
    this.schoolCode = schoolCode;
    this.departmentNumber = departmentNumber;
    this.lecturerID = lecturerID;
    this.lecturerName = lecturerName;
    this.moduleNo = moduleNo;
    this.creditHours = creditHours;
    this.classSize = classSize;
}

public String getSchoolCode() {
    return schoolCode;
}

public String getDepartmentNumber(){
    return departmentNumber;
}

public String getModuleNo() {
    return moduleNo;
}

public String getCreditHours() {
    return creditHours;
}

public String getClassSize() {
    return classSize;
}
public String getLecturerID() {
    return lecturerID;
}

public String getLecturerName() {
    return lecturerName;
}

public void setLecturerID(String lecturerID) {
    this.lecturerID = lecturerID;
}

public void setLecturerName(String lecturerName) {
    this.lecturerName = lecturerName;
}

public void setSchoolCode(String schoolCode) {
    this.schoolCode = schoolCode;
}

public void setDepartmentNumber(String departmentNumber){
    this.departmentNumber = departmentNumber;
}

public void setModuleNo(String moduleNo) {
    this.moduleNo = moduleNo;
}

public void setCreditHours(String creditHours) {
    this.creditHours = creditHours;
}

public void setClassSize(String classSize) {
    this.classSize = classSize;
}

ETC

Cheers

Upvotes: 0

Views: 358

Answers (3)

Stephen C
Stephen C

Reputation: 718758

A sort algorithm should not have 6 levels of nested loop. I don't think this particular attempt can be "rescued".

My advice would be to start again:

  • Implement a simple Bubblesort algorithm. Alternatively use the Collections.sort method provided by the Java SE libraries. (Read the javadocs ... even if you don't plan to use it not ... because it is a good thing to know about it!!)

  • Implement and use the Comparator or Comparable interfaces, or your own custom "compare two TeachingLoad objects" method.

Note that there should only be two levels of nesting in a Bubblesort, which looks to be the algorithm that you were trying to implement.


While I agree with @Ingo that Bubblesort is a poor algorithm, I think that this is entirely beside the point. If you have been asked to implement a sort as a programming exercise, and you have not been taught about advanced sorting algorithms, then trying to implement an advanced algorithm is "jumping the gun". By all means learn about it, but if you try something too far in advance of your current skills you are setting yourself up to fail.

Or to put it another way, don't "show off" :-)

On the other hand, if:

  • you should know (say) Quicksort, and
  • you are expected to implement the algorithm from scratch,

then my advice would be different.

Upvotes: 3

Alberto de Paola
Alberto de Paola

Reputation: 1160

Taking your input data, this is what I would do:

public class StringArraySort {

public static void main(String[] args) {

    List<String> arrayToSort = new ArrayList<String>();
    arrayToSort.add("BJM 300 AC4507 TOM_JONES"); 
    arrayToSort.add("BDM 290 DC4058 ALAN_FIELD"); 
    arrayToSort.add("ADG 350 BA3240 JON_THORN");
    arrayToSort.add("ADG 340 BA3240 JON_THORN");
    arrayToSort.add("ADF 340 BA3240 JON_THORN");

    Collections.sort(arrayToSort, customStringComparator);

    System.out.println(arrayToSort);

}

static final Comparator<String> customStringComparator = new Comparator<String>() {

    @Override
    public int compare(String o1, String o2) {
        String[] o1Columns = o1.split(" ");
        String[] o2Columns = o2.split(" ");

        if(o1Columns[2].compareTo(o2Columns[2]) == 0) {
            if(o1Columns[1].compareTo(o2Columns[1]) == 0) {
                // should it be first column?
                return o1Columns[0].compareTo(o2Columns[0]);
            } else {
                return o1Columns[1].compareTo(o2Columns[1]);
            }
        } else {
            return o1Columns[2].compareTo(o2Columns[2]);
        }
    }
}; }

I'm not sure I understood this statement:

third column within the second column within the third column?

So the columns may not be right.

As a rule of thumb always use a language construct, when there is one, in this case the Comparator.

EDIT: Seeing @Elliott Frisch's answer I think the best thing for you is to implement Comparable in your object.

2nd EDIT:

Here it is a method to do a simple bubble sort, but it is NOT advised for production code, as it performs very bad with large collections. Collections.sort(List list) is way faster, and if you look at the source you would see why.

public static <T extends Comparable<T>> void bubleSort(List<T> list) {
    boolean resort = false;
    for (int i = 0; i < list.size(); i++) {
        T t = list.get(i);
        int nextElementIndex = i + 1;
        if(nextElementIndex < list.size()) {
            T temp = list.get(nextElementIndex);
            if(t.compareTo(temp) > 0) {
                resort = true;
                list.set(nextElementIndex, t);
                list.set(i, temp);
            } else {
                continue;
            }
        } 
    }
    if(resort) {
        bubleSort(list);
    }
}

And here is the compareTo method from TeachingLoad:

public int compareTo(TeachingLoad o) {
        if(schoolCode.compareTo(o.schoolCode) == 0) {
            if(departmentNumber.compareTo(o.departmentNumber) == 0) {
                return lecturerID.compareTo(o.lecturerID);          
            }else {
                return departmentNumber.compareTo(o.departmentNumber);          
            }
        } else {
            return schoolCode.compareTo(o.schoolCode);
        }
    }

It's worth to mention that after a short Google search I found better algorithms than mine, like this, so I'm still not sure if this is what you are looking for.

Upvotes: 1

Elliott Frisch
Elliott Frisch

Reputation: 201429

I don't understand what you hope to achieve with your approach; just use a Comparator like this

public static class TeachingLoadComparator implements Comparator<TeachingLoad> {

  /**
   * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
   */
  @Override
  public int compare(TeachingLoad o1, TeachingLoad o2) {
    if (o1 == null) {
      if (o2 == null) {
        return 0;
      }
      return -1;
    } else if (o2 == null) {
      return 1;
    }
    if (o1 == o2) {
      return 0;
    }
    switch (o1.getSchoolCode().compareTo(o2.getSchoolCode())) {
    case -1:
      return -1;
    case 1:
      return 1;
    }
    switch (o1.getDepartmentNumber().compareTo(o2.getDepartmentNumber())) {
    case -1:
      return -1;
    case 1:
      return 1;
    }
    return o1.getLecturerID().compareTo(o2.getLecturerID());
  }

and then use it with

Collections.sort(loads, new TeachingLoadComparator());

Upvotes: 2

Related Questions