3

I have a class, lets say CargoShip, which is a derived class of 'Starcraft', which implements the interface IStarcraft.

I have a function public static ArrayList<String> getSpacecraftDescriptionsByCommissionYear(ArrayList<ISpacecraft> fleet)

Question: The CargoShip has toString which prints name, commissionYear, etc.. I want to do two things: First, I want to use each Ship's toString (like the one in the CargoShip), and second I want it to be sorted by CommissionYear.

Problem: I don't know how to access the commissionYear field after I've added the toString to the arrayList.

ArrayList<String> strCommissions = new ArrayList<String>();

        for(ISpacecraft flee : fleet)
        {
            strCommissions.add(flee.toString());
        }
        //Collections.sort(//What to write here??//);
        return strCommissions;
}

Here is the CargoShip class if you need it:

package starfleet;

public class CargoShip extends Spacecraft{

    private int numberOfSpaceCranes;
    static int count = 0;

    public CargoShip(String name, int commissionYear, float maximalSpeed,int cargoCapacity, int numberOfSpaceCranes)
    {
        this.name = name;
        this.commissionYear = commissionYear;
        if(MaximalSpeed())
            this.maximalSpeed = maximalSpeed;
        this.cargoCapacity = cargoCapacity;
        this.numberOfSpaceCranes = numberOfSpaceCranes;
        count++;
    }

    public int getNumberOfSpaceCranes ()
    {
        return this.numberOfSpaceCranes;
    }


    @Override
    public String getName() {

        return this.name;
    }
    @Override
    public int getCommissionYear() {
        return this.commissionYear;
    }
    @Override
    public float getMaximalSpeed() {
        if(MaximalSpeed())
            return this.maximalSpeed;
        else
            return 0f;
    }
    @Override
    public int getCargoCapacity() {
        return this.cargoCapacity;
    }
    @Override
    public int getFirePower() {
        return this.firePower;
    }

    @Override
    public int getAnnualMaintenanceCost() {
        int cost = 0;
        this.commissionYear = 2000;

        cost += getCommissionYear();
        cost += (500 * this.numberOfSpaceCranes);
        cost += (2 * getCargoCapacity()); //To check: TotalCargoWeightCapacity?
        // TODO Auto-generated method stub
        return 0;
    }

    public String toString()
    {
        return
        "Name = " + getName() + System.lineSeparator() +
        "CommissionYear = " + getCommissionYear() + System.lineSeparator() +
        "MaximalSpeed = " + getMaximalSpeed() + System.lineSeparator() +
        "CargoCapacity = " + getCargoCapacity() + System.lineSeparator() +
        "FirePower = " + getFirePower() + System.lineSeparator() +
        "AnnualMaintenanceCost = " + getAnnualMaintenanceCost() + System.lineSeparator() + 
        "numberOfSpaceCranes = " + getNumberOfSpaceCranes() + System.lineSeparator();
    }
}
Ilan Aizelman WS
  • 1,630
  • 2
  • 21
  • 44
  • Well by the time you've converted them into strings, you *can't* sort by commission year, because you only have the strings. I would copy the list, sort the copy, *then* convert to strings... – Jon Skeet May 19 '17 at 17:20
  • How can I sort the copy by commissionYear? because when I do it, only the commissionYear is returned. @JonSkeet – Ilan Aizelman WS May 19 '17 at 17:21
  • See http://stackoverflow.com/questions/2535124 – Jon Skeet May 19 '17 at 17:22
  • @JonSkeet I'm not sure how to follow after seeing the link. Let me explain again, Every ship has its own (maybe overloaded) constructor, so I can't use new. First question - How can I add to 'strCommissions' (String ArrayList) all the ship objects available? After adding, how can I sort them via commissionYear? – Ilan Aizelman WS May 19 '17 at 17:31
  • is `fleet` a list ? – Ousmane D. May 19 '17 at 17:32
  • Forget `strCommissions` to start with. You have three tasks: 1) Copy the list. 2) Sort the copy by commission year (as per the link). 3) Create a list of strings. You already know how to do step 3. Step 1 is just a matter of using the `ArrayList` constructor that accepts another list. Focus on step 2, which the other answer already helps you with. – Jon Skeet May 19 '17 at 17:33
  • @Aominè Yes, It is a list that contains ships. – Ilan Aizelman WS May 19 '17 at 17:35

2 Answers2

2

First, you can copy the list fleet into a new one:

ArrayList<ISpacecraft> objects = new ArrayList<>(fleet);

then you can sort it by commission year:

Collections.sort(objects, Comparator.comparingInt(ISpacecraft::getCommissionYear));

then create the list of Strings:

ArrayList<String> strCommissions = new ArrayList<String>();
objects.forEach(o -> strCommissions.add(o.toString()));

thus your function becomes:

public static ArrayList<String> getSpacecraftDescriptionsByCommissionYear(ArrayList<ISpacecraft> fleet){
       ArrayList<ISpacecraft> objects = new ArrayList<>(fleet);
       Collections.sort(objects, Comparator.comparingInt(ISpacecraft::getCommissionYear));
       ArrayList<String> strCommissions = new ArrayList<String>();
       objects.forEach(o -> strCommissions.add(o.toString()));
       return strCommissions;
}

reading:

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
  • Yup, your code works. I still keep reading how Comparator works, I will update. Thanks Aomine! I will accept your answer soon. – Ilan Aizelman WS May 19 '17 at 17:50
  • This is what I am using: http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html – Ilan Aizelman WS May 19 '17 at 17:53
  • 1
    Alright, that's a good link as well, however, I have appended a link which I found useful when I first started learning about comparators. – Ousmane D. May 19 '17 at 17:55
  • What is ISpacecraft::getCommissionYear, how can it be done without using this or lambda exprations? I mean by creating a new Comprator(){} – Ilan Aizelman WS May 19 '17 at 18:25
  • Something like this: Collections.sort(objects, new Comparator() {public int compare(ISpacecraft num1, ISpacecraft num2) {return num1.compareTo(num2.getCommissionYear();}}); – Ilan Aizelman WS May 19 '17 at 18:25
  • 1
    this --> `ISpacecraft::getCommissionYear` is called a [**method reference**](https://www.codementor.io/eh3rrera/using-java-8-method-reference-du10866vx) and is much more concise. However, this is how you'd go about doing it the way you've mentioned `Collections.sort(objects, new Comparator() { @Override public int compare(ISpacecraft o1, ISpacecraft o2) { return o1. getCommissionYear() - o2. getCommissionYear(); } });` – Ousmane D. May 19 '17 at 18:30
  • 1
    Works perfect. I need to investigate the compare function now, because I didn't use minus, instead i tried using the compareTo which caused an error. – Ilan Aizelman WS May 19 '17 at 18:32
  • Do you have some minutes to help me in chat? @Aomine – Ilan Aizelman WS May 19 '17 at 19:31
1

You should implement Comparable and implement compareTo method or as mentioned above Comparator can be used.

public int compareTo(CargoShip otherCargoShip) {
    int i = Name .compareTo(other.Name );
    if (i != 0) return i;

    i = CommissionYear.compareTo(other.CommissionYear);
    if (i != 0) return i;

    return Integer.compare(MaximalSpeed , other.MaximalSpeed );
}
gati sahu
  • 2,576
  • 2
  • 10
  • 16