Benjamin Lindqvist
Benjamin Lindqvist

Reputation: 4610

Want to sort an ArrayList of objects by several different attributes

I've got this class called Block (each Block has an x value and a y value). I've created a bunch of these and put them all in a list. I've managed to sort the list by x-value:

public class Block implements Comparable<Block> {
...
public int compareTo(Block block2){
    return this.x - block2.x;
}

But I want to be able to sort the list both by x and by y-value at my leisure. Is this doable somehow?

Upvotes: 2

Views: 851

Answers (4)

JNL
JNL

Reputation: 4703

A solution with Enums;

public static enum Order implements Comparator {
     ByX() {
        public int compare(Block b1, Block b2) {
           return b1.x - b2.x;
        }
     },

     ByY() {
        public int compare(Block b1, Block b2) {
           // TODO: Should really use a collator.
           return b1.y - b2.y;
        }
};

Then you call it by,

Collections.sort(blocks, Order.ByX);

Upvotes: 0

arshajii
arshajii

Reputation: 129477

You can implement two Comparators:

enum BlockSort implements Comparator<Block> {
    XSORT {
        @Override
        public int compare(Block b1, Block b2) {
            return b1.x - b2.x;
        }
    },

    YSORT {
        @Override
        public int compare(Block b1, Block b2) {
            return b1.y - b2.y;
        }
    }
}

Then pass the appropriate instance XSORT/YSORT as a second argument to the sort method. For example:

Collections.sort(blockList, BlockSort.XSORT);

Additionally, if by-x isn't the natural ordering of Block instances, it would likely be wiser to not make Blocks Comparable at all.

Upvotes: 4

Josh M
Josh M

Reputation: 11939

Much like @arshajii's answer, you could utilize an enum for the various different sorting methods, code shown below:

public enum BlockSorting implements Comparator<Block> {
    X{
        public int compare(final Block b1, final Block b2){
            return b1.x - b2.x;
        }
    },
    Y{
        public int compare(final Block b1, final Block b2){
            return b1.y - b2.y;
        }
    };
}

The advantage to using this way is that you could easily add more sorting methods (without creating a new enum each time). For example, to sort the collection of Blocks using the X, you could do something like this:

Collection<Block> blocks = ....;
Collections.sort(blocks, BlockSorting.X);

Upvotes: 1

Arnaud Denoyelle
Arnaud Denoyelle

Reputation: 31215

You can use 2 Comparators to achieve this.

public class XComparator implements COmparator<Block>{
  public int compare(T o1, T o2){
    ...
  }
}

and :

public class YComparator implements COmparator<Block>{
  public int compare(T o1, T o2){
    ...
  }
}

Then use one of them to sort:

Collections.sort(list, new XComparator());
Collections.sort(list, new YComparator());

Upvotes: 2

Related Questions