1

I aim to sort an arraylist of a class

 public class AnimSprite
    {
    float x,y,z;
    //...//
    }

ArrayList<AnimSprite> listofsprites = new ArrayList<AnimSprite>();

    //...//

list.add( new AnimSprite(1f,10f,0f) );      //x,y,z
list.add( new AnimSprite(15f,25f,1f) );
list.add( new AnimSprite(30f,-62f,0f) );
list.add( new AnimSprite(150f,-62f,2f) );
list.add( new AnimSprite(55f,-65f,0f) );

    //...//

Then of course I loop to draw it

for (AnimSprite s: listofsprites) { s.draw();}

Before draw instruction, how could we sort the array list ? (ordered by y ascending and then z ascending)

Eg expected result:

obj0 -> AnimSprite(55f,-65f,0f)
obj1 -> AnimSprite(30f,-62f,0f) 
obj2 -> AnimSprite(1f,10f,0f)
obj3 -> AnimSprite(15f,25f,1f)
obj4 -> AnimSprite(150f,-62f,2f)

for the moment, as below, I sort ascending by y and z but I am not sure it is state of art?

  public static class AnimSprite implements Comparable<AnimSprite >
    {
    //...//
   Override
       public int compareTo(AnimSprite o)
    {
        float result = this.z - o.z;
        if (result == 0f) result = this.y - o.y;
        return ((int)(result));
        }   
5
  • I suggest you to try it yourself using the Comparator interface: docs.oracle.com/javase/7/docs/api/java/util/Comparator.html. If you still have a hard time, pls reply and we can work through it. Commented Nov 5, 2019 at 10:34
  • It's not topic itself, but I would suggest to use interface instead of classes where possible, for example: ArrayList<AnimSprite> listofsprites = new ArrayList<AnimSprite>(); should be List<AnimSprite> listofsprites = new ArrayList<AnimSprite>(); Commented Nov 5, 2019 at 10:35
  • thanks but the final point is sorting by 2 floats Commented Nov 5, 2019 at 11:47
  • Collection.sort(list) Commented Nov 5, 2019 at 11:57
  • Please focus on sorting by 2 float attributes properly Commented Nov 5, 2019 at 12:04

3 Answers 3

3

You can use Collection.sort(list) to sort your ArrayList but AnimSprite must implement the Comparable Interface to let the sort method to know how to compare two AnimSprite objects.

public class AnimSprite implements Comparable
{
    float x,y,z;
    //...//

   @Override
   public int compareTo(AnimSprite o)
{
    float result = this.z - o.z;
    if (result == 0f) result = this.y - o.y;
    return ((int)(result));
    }   
}

ArrayList<AnimSprite> listofsprites = new ArrayList<AnimSprite>();

    //...//

listofsprites.add( new AnimSprite(1f,10f,0f) );      //x,y,z
listofsprites.add( new AnimSprite(15f,25f,1f) );
listofsprites.add( new AnimSprite(30f,-62f,0f) );
listofsprites.add( new AnimSprite(150f,-62f,2f) );
listofsprites.add( new AnimSprite(55f,-65f,0f) );

//...//

Collection.sort(listofsprites);

for (AnimSprite s: listofsprites) { s.draw();}

Another solution is to use the overloaded method sort that accept the Comparator implementation as second argument, and use the Lambda expression to write less code:

Collections.sort(listofsprites, (s1, s2) -> {
    float result = s1.z - s2.z;
    if (result == 0f) result = s1.y - s2.y;
    return ((int)(result));
});
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, I moved forward with comparable interface. However I can't figure simpliest way for 2 attributes sorting (eg y and z)?
@Chronoslog see my edit: I implemented your comparing logic inside the lambda
I will go to first option more efficient in terms of response time M1> 291537 nanoSecs (@Override ... compareTo(AnimSprite o)) whereas M2> 48145753 nanoSecs (Collections.sort(listofsprites, (s1, s2) -> ...)
0

There are two simple ways to achieve what you want. Both boil down to the idea that the elements of the array should be "comparable" to each other.

Option 1:

Implement Comparable interface in AnimSprite. Define compareTo method (that you'll have to since you implement the interface) to rely on 2 numbers for comparison.

Then use:

Collections.sort(yourArray);

Option 2:

Can be used when you can't really change AnimSprite class. In this case you can implement the Comparator interface effectively externalizing comparison logic:

Collections.sort(yourArray, new Comparator<AnimSprite> {
     public int compare(AnimSprite s1, AnimSprite s2) {
                ...
     }
 });

Of course you can also use lambda if you're using java 8+

1 Comment

sorry question is not how to sort java object but specific to by 2 floats (not Integer, or String or whatever...)
0

Yes. You can also do something like this:

    Collections.sort(list,
            Comparator.comparing((AnimSprite a) -> a.z)
                    .thenComparing((AnimSprite a) -> a.y));

1 Comment

thank you it works but execution times seams longer: M1> 291537 nanoSecs (@Override ... compareTo(AnimSprite o)) M2> 48145753 nanoSecs (Collections.sort(listofsprites, (s1, s2) -> ...) M3> 48187767 nanoSecs ( Comparator.comparing((AnimSprite a) -> a.z ....thenComparing ...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.