1

For a project in school, I was asked to write a program that loops through the values in an ArrayList named revenues and prints whether or not if the numbers withen revenues increased, decreased, or stayed the same while it went through the ArrayList.

This is what I wrote

        System.out.println("Year 1: No comperison");
        for (int i = 0; i < revenues.size(); i = i + 1){
            if (revenues.get(i) < revenues.get(i+1)){
                System.out.println("Year "+ (i) +": increased");
            } else if (revenues.get(i) > revenues.get(i+1)){
                System.out.println("Year "+ (i) +": decreased");
            } else {
                System.out.println("Year "+ (i) +": stayed the same");
            }
        }

But whenever I ran the program, it shows me an error message because of this code.

This is the error

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 5 out of bounds for length 5
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
    at java.base/java.util.Objects.checkIndex(Objects.java:359)
    at java.base/java.util.ArrayList.get(ArrayList.java:427)
O D E
  • 23
  • 5
  • 1
    have you tried debugging your program? – HariHaravelan Nov 30 '22 at 06:01
  • Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 5 out of bounds for length 5 at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100) at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106) at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302) at java.base/java.util.Objects.checkIndex(Objects.java:359) at java.base/java.util.ArrayList.get(ArrayList.java:427) at Quiz6.quize103.main(quize103.java:59) – O D E Nov 30 '22 at 06:05
  • 1
    should you start from 1 or 0? or you should start from 0, but if it is 0, then you should print "Year 1: No comperison" perhaps? should you compare item at i with item at i+1 or item at i-1? if you compare with item i+1, should you update the for condition where to stop? I hope my questions help you to point where your fix should be. – fauzimh Nov 30 '22 at 06:06
  • Thank you @fauzimh! Your questions helped and I found the problem in my code. – O D E Nov 30 '22 at 06:18

2 Answers2

1

Thanks to user fauzimh who asked me some insightful questions, I found the answer to my problem. Turned out that by adding when comparing, I would be going over the length of my ArrayList, so all I had to do was subtract.

Here is the updated code.

   System.out.println("Year 1: No comparison");
   for (int i = 1; i < revenues.size(); i = i + 1){
       if (revenues.get(i) < revenues.get(i-1)){
           System.out.println("Year "+ (i+1) +": decreased");
       } else if (revenues.get(i) > revenues.get(i-1)){
           System.out.println("Year "+ (i+1) +": increased");
       } else {
           System.out.println("Year "+ (i+1) +": stayed the same");
       }
   }

I hope I am right because it seemed to work.

O D E
  • 23
  • 5
  • 1
    Yes, this technique is fine, however developers will often start from an index of zero to ensure bounds are clearly defined. Whenever you attempt to access a `previous` or `next` index in an array without any type of sanity checking when looping, you will ultimately risk the chance of being out of bounds. For this reason, it's often safer and easier to read to simply stash the value you wish to compare from a previous iteration. I've provided an example answer which illustrates this. I believe if you revisit this code a year later, you will agree that it's easier to understand this way. :) – tresf Nov 30 '22 at 06:57
  • 1
    thanks @tresf. I learned a lot from this short reply and your example. – O D E Nov 30 '22 at 13:29
1

Some general improvements:

  • Store the year you want to compare in a dedicated variable (e.g. previousYear)
  • Try to loop with an index of 0, it's easier to keep track of since that's what Java Arrays and Java Lists use!
  • If you want to show 0 as your 1st year, just add the +1 to the lines showing your output.
  • i++ is shorthand for i = i + 1

In my case, I've initialized a variable called previousYear as -1, which will show an increase the first year no matter what, since there's nothing to compare to. Hopefully this helps. :)

// Create the list of revenues
List<Integer> revenues = Arrays.asList(new Integer[]{ 1234, 2345, 2123, 2123 });

// Default last years revenue to -1 since we don't know it yet
int previousYear = -1;

// Compare each year to the previous year
for (int i = 0; i < revenues.size(); i++){
    // Store the current year's revenue
    int currentYear = revenues.get(i);

    // Show comparison to the screen
    if (previousYear == -1) {
        System.out.println("Year "+ (i+1) +": no comparison");
    } else if (currentYear > previousYear) {
        System.out.println("Year "+ (i+1) +": increased");
    } else if (currentYear < previousYear) {
        System.out.println("Year "+ (i+1) +": decreased");
    } else {
        System.out.println("Year "+ (i+1) +": stayed the same");
    }

    // Store as previous year for next loop
    previousYear = currentYear;
}
tresf
  • 7,103
  • 6
  • 40
  • 101