1

I have a Vector of objects. Each object has three fields-

int v1, v2, v3;

I need to arranged this list of objects so that they are ascending by these values. What I mean by this is that v1 is ordered first, and then if v1 is the same in any objects, v2 is ordered and if v2 is the same v3 is ordered- like when you order words alphabetically, first you order the first character then the second and so on.

I know what I'm trying to say may sound confusing, please tell me if I need to reword it

Therefore I need to get my input:

object 1: v1 = 5, v2 = 6, v3 = 1;
object 2: v1 = 7, v2 = 5, v3 = 3;
object 3: v1 = 5, v2 = 1, v3 = 3;
object 4: v1 = 2, v2 = 5, v3 = 5;
object 5: v1 = 8, v2 = 4, v3 = 6;

to be ordered like this:

object 4: v1 = 2, v2 = 5, v3 = 5;
object 3: v1 = 5, v2 = 1, v3 = 3;
object 1: v1 = 5, v2 = 6, v3 = 1;
object 2: v1 = 7, v2 = 5, v3 = 3;
object 5: v1 = 8, v2 = 4, v3 = 6;

As you can see object 3 and 1 have the same v1, therefore they are ordered by v2

Please tell me if I need to elaborate further

Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
John
  • 346
  • 1
  • 11
  • You might want to have your Class implement the 'Comparable' interface: See this SO thread: http://stackoverflow.com/questions/3718383/java-class-implements-comparable – Liang Jan 23 '16 at 04:44
  • So, you have to implement [`Comparable`](https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html) interface and then call built-in [`sort`](https://docs.oracle.com/javase/tutorial/collections/interfaces/order.html) method. What's the problem? – awesoon Jan 23 '16 at 04:45
  • ill just try it out, thanks for the quick response – John Jan 23 '16 at 04:49

3 Answers3

1

Use a Sort - with a Comparable (on the type) or with a separate Comparator. These are covered elsewhere.

The 'tricky' bit is to write the comparing method not-too-painfully. This can be done following one of several templates (in pseudo-code, the compareTo method is to be written as appropriate such that it follows the Comparable/Comparator contract):

// Objects supplied to comparing function
Vector a = ..
Vector b = ..

// First component in which the values are not equals
// establishes a 'winner'
int cmp = 0;
if ((cmp = compareTo(a.v1, b.v1)) != 0) return cmp;
if ((cmp = compareTo(a.v2, b.v2)) != 0) return cmp;
if ((cmp = compareTo(a.v3, b.v3)) != 0) return cmp;
return 0;

There are, of course, multiple variations of the above including explicit / nested if-constructs and ternary conditional chaining. The code above is written the way it is to show both single-evaluation of comparing the individual elements and consistency/extensibility.

For numbers, noting overflow and that the result may not be an integer etc., compareTo(n1, n2) is sometimes expressed as n1 - n2. If the values in the Vectors are floating point numbers it may be worth taking an epsilon into account when doing the comparison.


Here is another visualization of the logic:

if (a.v1 < b.v1) return -1;
else if (a.v1 > b.v1) return 1;
else
  if (a.v2 < b.v2) return -1;
  else if (a.v2 > b.v2) return 1;
  else
    if (a.v3 < b.v3) return -1;
    else if (a.v3 > b.v3) return 1;
    else
      return 0;
Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
1

Use below code for sorting any number and any level of sorting.

import java.util.*;

public class SortObj implements Comparable{

    int v1=0, v2=0, v3=0;

    public SortObj(int v1, int v2, int v3) {
        this.v1 = v1;
        this.v2 = v2;
        this.v3 = v3;
    }

    public static void main(String[] args) {
        SortObj o1 = new SortObj(1,2,3);
        SortObj o2 = new SortObj(1,4,3);
        SortObj o3 = new SortObj(1,50,3);
        SortObj o4 = new SortObj(1,30,30);
        SortObj o5 = new SortObj(2,20,3);
        SortObj o6 = new SortObj(3,20,3);

        List<SortObj> list = new ArrayList<>();
        list.add(o1);
        list.add(o2);
        list.add(o3);
        list.add(o4);
        list.add(o5);
        list.add(o6);

        Collections.sort(list);
        for(SortObj sortObj : list){
            System.out.println(sortObj.toString());
        }
    }


    @Override
    public String toString() {
        return  String.format("%02d", v1)+
                String.format("%02d", v2)+
                String.format("%02d", v3);
    }
    @Override
    public int compareTo(Object o) {
        return this.toString().compareTo(o.toString());
    }
}
Piyush Ghediya
  • 1,754
  • 1
  • 14
  • 17
  • Such a use of String.format is clever, but has some drawbacks that should be indicated. The code above is only guaranteed to work if all the component values are in the range [0..99.) Values outside this range, including negative numbers, will produce unexpected results. – user2864740 Jan 23 '16 at 06:54
  • Yes, but this is kind of clue which we can generalize and validate custom i.e String.format with custom level of format to n th number padding. – Piyush Ghediya Jan 23 '16 at 07:07
  • Even with an arbitrary (but carefully selected) level of padding a string approach will fail when negative numbers are introduced: "-1" is ordered *before* "-2", despite being the larger number. – user2864740 Jan 23 '16 at 07:12
  • ["-2", "-3"] is ordered as ["-2", "-3"] The correct order for [-2,-3] is [-3,-2]. For two negative numbers the string ordinal ordering trumps the correct natural number ordering. – user2864740 Jan 24 '16 at 00:54
0

you can implement Comparable in your class ObjectX

public int compareTo(final ObjectX 2bj1, final ObjectX obj2) {
...    
}
CodeIsLife
  • 1,205
  • 8
  • 14
  • Sure, but I don't think this alone covers what the OP is asking. Something like the 2-axis ordering (easily expandable to 4-axis) shown in http://stackoverflow.com/a/3718515/2864740 would be relevant. – user2864740 Jan 23 '16 at 04:47