Home > Blockchain >  Searching for a String in an ArrayList of Objects
Searching for a String in an ArrayList of Objects

Time:05-28

I have been trying to figure this out for hours and I have had no luck doing so, I'm trying to iterate over my Arraylist<Booking> which utilizes my Booking class file and trying to understand how I'm able to search it for the matching, case-insensitive term.

this is my current method:

private void searchBookings() {
        if (bookings.size() <= 0) {
            JOptionPane.showMessageDialog(null, "There are no bookings.", "Search Bookings", 3);
        } else {
            String searchTerm = JOptionPane.showInputDialog(null, "Please input search term: ", "Search Bookings", 3);
            for (int i = 0; i < bookings.size(); i  ) {
                while (!bookings.get(i).getStudent().getName().equalsIgnoreCase(searchTerm)) {
                    i  ;

                    if (bookings.get(i).getStudent().getName().equalsIgnoreCase(searchTerm)) {
                        String output = String.format("%-30s%-18s%-18b$%-11.2f\n", bookings.get(i).getStudent(), bookings.get(i).getLessons(), bookings.get(i).isPurchaseGuitar(), bookings.get(i).calculateCharge());
                        this.taDisplay.setText(heading   "\n"   output   "\n");
                    }
                }
            }

        }
        JOptionPane.showMessageDialog(null, "There is no booking with that name.", "Search Bookings", 3);

    }

I know it's messy but, just trying to make do.

I am trying to retrieve the name of the booking as I am searching by name as well as provide an error message if that names does not exist, to do that I must use bookings.getStudent().getName() I have had some luck as I can return the value but now I am not able to provide my error message if I do not find it. Any help is appreciated.

package com.mycompany.mavenproject1;

public class Booking {

    private Student student;
    private int lessons;
    private boolean purchaseGuitar;

    // CONSTANTS
    final int firstDiscountStep = 6;
    final int secondDiscountStep = 10;

    final int tenPercentDiscount = 10;

    final int twentyPercentDiscount = 5;
    final double LESSON_COST = 29.95;
    final double GUITAR_COST = 199.00;
    double LESSON_CHARGE = 0;
    final int MINIUMUM_LESSONS = 1;

    public Booking() {

    }
    public Booking(Student student, int lessons, boolean purchaseGuitar) {
        this.student = new Student(student.getName(), student.getPhoneNumber(), student.getStudentID());
        this.lessons = lessons;
        this.purchaseGuitar = purchaseGuitar;
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    public int getLessons() {
        return lessons;
    }

    public void setLessons(int lessons) {
        this.lessons = lessons;
    }

    public boolean isPurchaseGuitar() {
        return purchaseGuitar;
    }

    public void setPurchaseGuitar(boolean purchaseGuitar) {
        this.purchaseGuitar = purchaseGuitar;
    }

    public double calculateCharge() {
        double tempCharge;
        if (lessons < firstDiscountStep) {
            LESSON_CHARGE = (lessons * LESSON_COST );
        } else if (lessons < secondDiscountStep) {
            tempCharge = (lessons * LESSON_COST) / tenPercentDiscount;
            LESSON_CHARGE = (lessons * LESSON_COST) - tempCharge;
        } else {
            tempCharge = (lessons * LESSON_COST) / twentyPercentDiscount;
            LESSON_CHARGE = (lessons * LESSON_COST) - tempCharge;
        }

        if (isPurchaseGuitar()) {
            LESSON_CHARGE  = GUITAR_COST;
        }
        return LESSON_CHARGE;
    }

    @Override
    public String toString() {
        return  student   ","  lessons   ","   purchaseGuitar  ","   LESSON_COST;
    }
}

CodePudding user response:

If I understood you correctly, you are searching for a given student name in your collection of bookings. And if it is present, set a formatted text.

First of all, use a for-each loop, because you don't use the index. Secondly, return from the for-each loop, when you found your student.

private void searchBookings() {
    if (bookings.size() <= 0) {
        JOptionPane.showMessageDialog(null, "There are no bookings.", "Search Bookings", 3);
    } else {
        String searchTerm = JOptionPane.showInputDialog(null, "Please input search term: ", "Search Bookings", 3);
        for (final Booking booking : bookings) // for-each
        {
            if (booking.getStudent().getName().equalsIgnoreCase(searchTerm))
            {
                String output = booking.getFormattedOutput();
                this.taDisplay.setText(heading   "\n"   output   "\n");
                return; // break out of the loop and method and don't display dialog message
            }
        }

    }
    JOptionPane.showMessageDialog(null, "There is no booking with that name.", "Search Bookings", 3);
}

Then there are multiple other things, which you could improve.

  1. Don't get all the data from a booking just to format it externally. Let the Booking class handle the formatting and return you the string you desire. (move the formatting in a function inside the Booking class)
  2. Instead of recreating a Student you receive in your Booking constructor, make the Student class immutable, and then you can just reuse the object provided.
  3. Try also making the Booking class immutable. You provided some setters, but do you really want to change the student in a booking? Or would you rather create a new booking for the other student?
  4. The calculteCharge method could be stateless. Just get the LESSON_CHARGE value and hold it in a local variable. Your method would also get threading-proof.
  5. Make your constants final and better yet make them members of the class (by adding the static modifier) instead of every member.
  6. Lastly, representing a money amount with a floating (double is better but not good either) number, you will run into funny situations. Try this calculation: 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 for example. One way would be to create a Money class which holds the value in cents as an integer. And when you want to display the amount you can divide it by 100 and format it accordingly. That way, you can also restrict it become negative.

PS: Sometimes we desperately try to find a solution that we don't give ourselves some rest. After a little break, you might recognize the problem. Oh and try debugging with breakpoints. Or this, if you use IntelliJ IDEA (which I would highly recommend, the community edition is free).

CodePudding user response:

You're re-incrementing your counter variable, which is really not going to help. Try the following:

private void searchBookings() {
    if (bookings.size() <= 0) {
        JOptionPane.showMessageDialog(null, "There are no bookings.", "Search Bookings", 3);
    } else {
        String searchTerm = JOptionPane.showInputDialog(null, "Please input search term: ", "Search Bookings", 3);
        boolean studentFound = false;
        for (int i = 0; i < bookings.size(); i  ) {

            if (bookings.get(i).getStudent().getName().equalsIgnoreCase(searchTerm)) {
                String output = String.format("%-30s%-18s%-18b$%-11.2f\n", bookings.get(i).getStudent(),
                        bookings.get(i).getLessons(), bookings.get(i).isPurchaseGuitar(),
                        bookings.get(i).calculateCharge());
                this.taDisplay.setText(heading   "\n"   output   "\n");
                studentFound = true;
                break;
            }
        }

    }
    if (!studentFound) {
        JOptionPane.showMessageDialog(null, "There is no booking with that name.", "Search Bookings", 3);
    }

}
  • Related