How do I sort strings with integers and letters in order of least to greatest? (Java)

Viewed 274

I was given an assignment in which I have to:

A) Use an array list

and

B) From a set of data (that is in a text file) containing a runner's finishing time and their sex, output the times in order of Fastest Time, Fastest Male Time, and Fastest Female Time.

For example, the file will read something like:

6
48 F
52 M
43 F
49 F
50 M
57 F

Where the first line is the number of runners and the other lines are each runner's time and their sex (M for Male, F for Female)

then, the computer must print something like:

43 48 50

Note how the second-fastest female got the title of "fastest female" because the one that ran the race in 43 got the "fastest overall" title.

The most challenging part about this assignment for me is the fact that you have to deal with the time AND sex while sorting out which student is the fastest. I genuinely have no idea how to approach that problem.

So far what I have accomplished is That I have successfully read and transferred the data in the file and stored it as an ArrayList on the system. Here is the Arraylist Version:

    public class RaceClient {
    public static void main(String [] args) throws IOException {
    Scanner inFile = new Scanner(new File("input.txt"));

    ArrayList<String> times = new ArrayList<>();
    ArrayList timesnum = new ArrayList();

    while(inFile.hasNext()) {
        times.add(inFile.nextLine()); 
            }//end of while
     times.remove(0);
     int i=0;

     while( i <times.length()) {
         timesnum[i]= Integer.parseInt(times[i]);
     }

System.out.println(times);
}//end of main

    }//end of class

Any suggestions on what I should do or what I should import would be great

3 Answers

This is a very quick code-up, but will hopefully point you in the right direction.

If I were you, I would create first a very simple Participant object:

public class Participant implements Comparable {

    String time;
    String sex;

    public Participant(String time, String sex) {
        this.time = time;
        this.sex = sex;
    }

    public String getTime() {
        return time;
    }

    public String getSex() {
        return sex;
    }

    @Override
    public int compareTo(Object o) {
        return this.getTime().compareTo(((Participant) o).getTime());
    }
}

Our Participant object has the notion of time and sex, very simple. We also want it to implement Comparable and the overriden compareTo() method - this is needed, so we can compare our Participant objects by time.

Next, for every line in the file (except the first one, since that just shows the number of Participants), lets create the corresponding Participant objects and add them to the ArrayList. I am going to do this using a BufferedReader:

        BufferedReader in = new BufferedReader(new FileReader("...your-file..."));
        ArrayList<Participant> participants = new ArrayList<>();
        String str;

        //skip first line
        in.readLine();
        while ((str = in.readLine()) != null){
            //Split every line entry by space, so split e.g. 49 F into time 49 and sex F
            String[] splitString = str.split(" ");
            Participant p = new Participant(splitString[0], splitString[1]);
            participants.add(p);
        }

Then, lets sort our Participants ArrayList:

Collections.sort(participants);

Next, we straight away can now say who has the Fastest Time - that will be the first one in the ArrayList, regardless of Sex. After we get the Fastest Time, we can remove it from the ArrayList, since we no longer care about it:

System.out.println("Fastest Time: " + participants.get(0).getTime());
participants.remove(participants.get(0));

Next, we need to decide on what the next fastest time is - is it Male or Female Fastest Time? Lets create a separate private method for that:

private static void determineFastestSexTime(ArrayList<Participant> participants) {
    if (participants.get(0).getSex().equals("M")) {
        System.out.println("Fastest Male Time: " + participants.get(0).getTime());
    } else {
        System.out.println("Fastest Female Time: " + participants.get(0).getTime());
    }
}

Then use it like this:

 determineFastestSexTime(participants);

Once we have that, we can remove all the other times for this Sex since they would be slower than the Fastest (Sex) Time:

participants.removeIf(p -> (p.getSex().equals(participants.get(0).getSex())));

We are therefore left only with a Male list, or a Female list of Participants. Then its easy - grab the fastest time of the rest:

 determineFastestSexTime(participants);

Output:

Fastest Time: 43
Fastest Female Time: 48
Fastest Male Time: 50

I'd make three functions one for each requirement. This may not be the best way, but it works. Also, I have not done any work in Java recently.

Feel free to ask me more questions. Here's the solution to your problem:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;


public class StackOverflowProblem{

     public static void main(String []args){
        List<Runner> allRunners = new ArrayList<Runner>();

        //Add Runners to Array
        allRunners.add(new Runner(10.23, "FEMALE"));
        allRunners.add(new Runner(14.21, "MALE"));
        allRunners.add(new Runner(16.15, "FEMALE"));
        allRunners.add(new Runner(10.15, "FEMALE"));


        //Max Time
        Runner fastestRunner=getMaxTime(allRunners);

        System.out.println("FASTEST TIME");
        System.out.println(
            "Time: "+fastestRunner.getTime()+"\n"+
            "Gender: "+fastestRunner.getGender()+
            "\n"
        );


        //Fastest Female Time
        Runner fastestFemaleRunner=getMaxTimeFemale(allRunners);

        System.out.println("FASTEST FEMALE TIME");
        System.out.println(
            "Time: "+fastestFemaleRunner.getTime()+"\n"+
            "Gender: "+fastestFemaleRunner.getGender()+
            "\n"
        );


        //Fastest Male Time
        Runner fastestMaleRunner=getMaxTimeMale(allRunners);

        System.out.println("FASTEST MALE TIME");
        System.out.println(
            "Time: "+fastestMaleRunner.getTime()+"\n"+
            "Gender: "+fastestMaleRunner.getGender()+
            "\n"
        );

     }

     static class Runner{
        public double time;
        public String gender;

        public Runner(double time, String gender){
            this.time=time;
            this.gender=gender;
        }

        public Double getTime() {
            return this.time;
        }

        public String getGender(){
            return this.gender;
        }

     }



     public static Runner getMaxTime(List<Runner> allRunners){
        Runner max_runner=allRunners.stream()
            .min(Comparator.comparingDouble(Runner::getTime))
            .get();

        return max_runner;
     }

     public static Runner getMaxTimeFemale(List<Runner> allRunners){
        Runner maxFemaleRunner=allRunners.stream()
            .filter(runner->runner.getGender().equals("FEMALE"))
            .min(Comparator.comparingDouble(Runner::getTime))
            .get();

        return maxFemaleRunner;
     }

     public static Runner getMaxTimeMale(List<Runner> allRunners){
        Runner maxMaleRunner=allRunners.stream()
            .filter(runner->runner.getGender().equals("MALE"))
            .min(Comparator.comparingDouble(Runner::getTime))
            .get();

        return maxMaleRunner;
     }

}

Since you are using a arrayList, being given the total on the top of the file seems odd, as if you were using an array you'd need to now how big to initialize it as.

I would take advance of Java as a Object Oriented Language. What you could do is create a class called Runner that has fields (int speed, char sex). That way the arrayList could contain all the Runners, it would be a good way to sort using a overwritten compareTo method inside the Runner class. Once you have them sorted you could go through the arrayList to print in order of fastest times, and then print out the fastest male and female.

Your compareTo method could sort first by speed, and then by gender as it would be in a sorted way from fastest to slowest.

Related