6

I have a list of structs that I would like to sort according to a specific element of the struct:

private class myStruct {

    public Boolean GUI;
    public float CallTime;
    public String ReqID;
    public String ReqGUID;
    public String Stereotype;
    public String StereotypeGUID;

}

private List<myStruct> DataList = new ArrayList<myStruct>();

How could I sort DataList by the element "ReqID" without hardcoding it? Is there a possibility to use Arrays.sort()?

Florent
  • 12,310
  • 10
  • 49
  • 58
user1679802
  • 167
  • 1
  • 2
  • 11
  • I suggest consider using a `boolean` instead of `Boolean`, use `double` instead of `float`, make the fields `final` and `private` or package-local if you can. – Peter Lawrey Sep 18 '12 at 09:40

8 Answers8

2

You should use a Comparator.

 class YourComparator implements Comparator<myStruct>{

         public int compare(myStruct s1, myStruct s2){
              //here comes the comparison logic
         }
 }

And then use this form of the sort() method:

 Arrays.sort(T[] arrayToSort, Comparator<T> yourComparator);

It's not very clear whether you use a collection or an array as the data structure.

In case you use a List, then use Collections.sort().

Razvan
  • 9,925
  • 6
  • 38
  • 51
  • 1
    You cannot use `Arrays.sort()` with a `List`. Use `Collections.sort` instead. – vanje Sep 18 '12 at 09:35
  • Yes, but he mentioned Arrays.sort() even though in the beginning of the question he says something about a list. There is a small inaccuracy. – Razvan Sep 18 '12 at 09:37
  • But in his code he has a list and he asked, if he could use Array.sort()? So the answer is no. – vanje Sep 18 '12 at 09:38
  • Thank you all for the fast and great Help! I'm sorry for the missunderstanding in the title, I use a List. With Collection.sort() works as described Thank you! – user1679802 Sep 18 '12 at 11:40
1

For custom sorting you can implement the Comparable interface.

With this interface you create a method compareTo() which returns a negative number, 0 or a positive number. Based on the return code Collections.sort() can tell if the element has to be before or after another element.

A nice example how to use it can be found in this answer: java class implements comparable

Community
  • 1
  • 1
nkr
  • 3,026
  • 7
  • 31
  • 39
1

use the Comparator interface like this

public static void main(String[] args) {
    List<myStruct> DataList = new ArrayList<myStruct>();
    //ADD Objects to DataList here

    Collections.sort(DataList, new Comparator() {

        public int compare(Object o1, Object o2) {
            myStruct p1 = (myStruct) o1;
            myStruct p2 = (myStruct) o2;
            int ret = -1;
            //business logic here
            if (Integer.parseInt(p1.ReqGUID) == Integer.parseInt(p2.ReqGUID)) {
                ret = 0;
            } else if (Integer.parseInt(p1.ReqGUID) > Integer.parseInt(p2.ReqGUID)) {
                ret = 1;
            } else if (Integer.parseInt(p1.ReqGUID) < Integer.parseInt(p2.ReqGUID)) {
                ret = -1;
            }//end business logic
            return ret;
        }
    });

}

Here inside the Collections.sort() method I am implementing the Comparator interface and overriding the compare() method. This will actually sort your list based on the business logic you implemented inside the compare() method;

MaVRoSCy
  • 17,747
  • 15
  • 82
  • 125
1

Your class structure look strange to me.. You have public fields inside a private class.. Ideally your fields should be marked private and you can have getters and setters to access them..

As for your problem, you can take a look at two important interfaces taht are defined for this kind of job: - http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Comparator.html and http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Comparable.html..

You use Comparator when you want to have multiple ways to compare your class instance.. You can just create a class implementing the Comparator interface, and pass the instance of this class to Collections.sort() method to use this Comparator for sorting.. In this case, compare() method is used to do the job of comparison.

Alternatively, you can associate only one way of comparing a class instance by making that class implementing Comparable interface.. In this case you need to override compareTo() method..

Here's a sample code using Comparator: -

public class MyComparator implements Comparator<Box> {
    @Override
    public int compare(Box box0, Box box1) {
        int w0 = box0.getWeight();
        int w1 = box1.getWeight();

        return (w0 > w1? -1 : (w0 == w1) ? 0 : 1);
    }
}

public class Box {
    private int weight;

    public Box() {      
    }

    public Box(int weight) {
            this.weight = weight;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }
}

And Your Main

public class Main {

    public static void main(String args[]) {
        List<Box> boxList = new ArrayList<Box>();
        Collections.sort(boxList, new MyComparator());
    }
}

Hope it helps..

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
0

You can define your own Comparator and use Collections.sort(), passing that Comparator in. That way you can define different comparators for searching using different fields.

Alternatively your struct can implement the Comparable interface and Collections.sort() can sort using this. This is called using the natural sort order, since it's implicit to your class.

Here's the Java tutorial on sorting and ordering.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
0

Use java.util.Collections.sort() with a Comparator instance. See the JavaDocs.

vanje
  • 10,180
  • 2
  • 31
  • 47
0

Use Arrays.sort(T[] a, Comparator<? super T> c)

or Collections.sort(List a, Comparator c)

Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
0

Simplest solution

Just implement java.lang.Comparable interface in you class like following:

class MyStruct implements Comparable<MyStruct>{

  public Boolean GUI;
  public float CallTime;
  public String ReqID;
  public String ReqGUID;
  public String Stereotype;
  public String StereotypeGUID;

  @Override
  public int compareTo(MyStruct other) {
    return ReqID.compareTo(other.ReqID); 
    /* also you can use ReqID.compareToIgnoreCase(other.ReqID); */
  }

  @Override
  public String toString() {
    return "(" + ReqID + ")";
  } 
}

Override also toString() method just for printing.

Also, keep in mind that String's compareTo() method sorts using lexicographical order. In case you want numeric ID's it is better to use int or other numerical type. Following is complete code to sort using Arrays.sort() as well as Collections.sort() - choose what suits you :)

public class MyStructSort {

  private final static String[] STRUCT_IDS = {"C", "D", "A", "Aa", "B", "Z", "Aaa" };

  private static List<MyStruct> createList() {

    List<MyStruct> structList  = new ArrayList<MyStruct>();
    for (String id: STRUCT_IDS) {
      MyStruct struct = new MyStruct();
      struct.ReqID = id;
      structList.add(struct);
    }
    return structList;
  }

  public static void main(String[] args) {

    List<MyStruct> dataList = createList();

    /* Sort using Lists (Collections) */
    Collections.sort(dataList);
    System.out.println("List sort:\t" + dataList);

    /* Sort using arrays */
    MyStruct[] dataArray = dataList.toArray(new MyStruct[dataList.size()]); 
    Arrays.sort(dataArray);
    // print sorted array
    System.out.print("Array sort:\t");
    for (MyStruct struct: dataArray) {
      System.out.print(struct+" ");                        
    }
  }
}

This is just demonstration code, so some null-checks and getters and setters would be needed to make it perfect.

antoni.rasul
  • 648
  • 6
  • 12