'Count Occurrences of Seven Integers in Array

I have written the code below and it has comments attached. The application is to read seven integers entered by the user. The application then prints out the number of occurrences of each of the seven values.

The program crashes when I enter in the integers: 1 2 3 1 2 3 100

Error: Exception in thread "main" `java.lang.ArrayIndexOutOfBoundsException: 100` at u7a1_numofoccurrinsevenints.U7A1_NumOfOccurrInSevenInts.main(U7A1_NumOfOccurrInSevenInts.java:78)
/Users/davramirez/Library/Caches/NetBeans/8.2/executor-snippets/run.xml:53: Java returned: 1
BUILD FAILED (total time: 5 seconds)

I have tried using Integer.MAX_VALUE in the code to fix the problem. I know that my arrays should have 7 instead of 100. And that the input should not affect the program. I am stumped. The code is below:

package u7a1_numofoccurrinsevenints;

// Initialize scanner untility 
import java.util.Scanner;

/**
 *
 * @author davramirez
 */
public class U7A1_NumOfOccurrInSevenInts {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        
        
        /**
        * Call scanner method to take user input.
        * Print out student copy.
        * Print out instructions to enter seven numbers
        */
        System.out.println("Student's Copy");
        Scanner input = new Scanner(System.in);
        System.out.println("Enter seven numbers: ");
        /**
        * Initialize arrays number and count
        * Array number takes integer value from user.
        * Array count servers as counter in the program
        * Declare variable counter as integer.
        * Counter serves as counter in for loop to stop at 7
        */
        int [] number = new int[7]; 
        int [] count = new int[7];
        int counter = 0;
        
        /**
        * Declare variable i as integer
        * Declare variable tempHold as the integer with value of zero
        * Variable tempHold temporarily stores value
        * of the array number at a specific index
        */
        int i, tempHold = 0;


        /**
        * For loop that populates array number from  user input
        * Counter++ used to count seven values of the array
        * If statement that loops for counter to reach seven
        * When seven reach the program exits
        * stores user input to  number[] array
        */
        
        for(i=0; i < number.length; i++){
            number[i] = input.nextInt();
            counter++;
            
            if(counter == 7){
                break;
            }
        } // End of for loop

        /**
        * For loop that passes value of array
        * The value is stored in the tempHold variable
        * tempHold variable used as index value
        * Count array tracks total occurrences of each integer.
        */
        
        for(i = 0; i < number.length; i++){
                tempHold = number[i];
                count[tempHold]++;
            }// End of for looop

         /**
        * For loop prints out number plus the occurrence
        * If statement that checks with the integer is repeated
        * If the does not repeat the program prints time occurred
        * Else it uses times. This prints out grammatically correct results.
        */
        for(i=1; i < count.length; i++){

            if(count[i] > 0 && count[i] == 1){
             System.out.printf("Number %d occurs %d time.\n",i, count[i]);
             }
            else if(count[i] >=2){
                System.out.printf("Number %d occurs %d times.\n",i, count[i]);
            }
         }//end of for loop
    
    } 
}


Solution 1:[1]

You can do the same By using HashMap<Integer, Integer> as shown below.

package u7a1_numofoccurrinsevenints;

import java.util.HashMap;
import java.util.Scanner;

public class U7A1_NumOfOccurrInSevenInts  {

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int[] inputArray = new int[7];
        System.out.print("Enter seven numbers: ");
        for (int i = 0; i < 7; i++) {
            inputArray[i] = input.nextInt();
        }

        HashMap<Integer, Integer> numberCountMap = new HashMap<>();
        for(int element : inputArray){
            numberCountMap.put(element, (numberCountMap.containsKey(element)) ? numberCountMap.get(element) + 1 : 1);
        }
        numberCountMap.forEach((key, value) -> System.out.println("Number " + key + " occurs " + value + " times."));
    }
}

Solution 2:[2]

Well, your issue occurs because you are trying to access the index 100 in your count[] array, which is only of size 7. So, this line is faulty: count[tempHold]++;.

Altogether, your approach is overly complicated and can't work out. Better and cleaner ways to do this have been posted thousand of times on this site, so I won't post a detailed snippet for your issue here. But you can check out this solution, which also contains an explanation.

Edit:

Apparently you just basically took this response from a previous quesiton and slightly modified it. If you scrolled further down, you would have found a more suitable answer aswell.

Solution 3:[3]

Has your instructor mentioned the single responsibility principle or test-driven development? This assignment is as good a time as any to discuss those.

Your main() is doing too much: shepherding input from the user into an array, processing that array and reporting the results. I recommend you create at least one separate "method," a function that takes in an array of integers and counts occurrences of numbers in that array.

I see you're using NetBeans. Wise choice. That means you have access to JUnit and TestNG. You can use one of those testing frameworks to help you make your program more modular and easier to test. That also means easier to pinpoint the source of the problem when something goes wrong.

Taking Trushit's idea to use HashMap<Integer, Integer>, make a stub for a function that takes in an array of integers and returns a HashMap<Integer, Integer>.

    // STUB TO FAIL THE FIRST TEST
    static HashMap<Integer, Integer> countOccur(int[] numbers) {
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(0, 0);
        return map;
    }

Next, put your mouse on the line declaring the class("public class U7A1_NumOfOccurrInSevenInts") and click on the lightbulb that replaces the line number. Select the option to create a new JUnit test class.

Sometimes NetBeans comes up with good tests, sometimes not. But if there are no warnings, you can simply ignore those tests for the time being. In the test class, add this test:

    @Test
    public void testAllNumbersTheSame() {
        int[] numbers = {10, 10, 10, 10, 10, 10, 10};
        HashMap<Integer, Integer> expected = new HashMap<>();
        expected.put(10, 7); // Ten occurs seven times
        HashMap<Integer, Integer> actual = countOccur(numbers);
        assertEquals(expected, actual);
    }

(You might need to use the fully qualified name for countOccur() or add a static import)

Run the test (Run > Test File) or use the keyboard shortcut (Ctrl-F6 on Windows). This test should fail. Make it pass with a simple change to countOccur():

        map.put(10, 7);

Now write that expects different results. To use your example,

    @Test
    public void testDifferentNumbers() {
        int[] numbers = {1, 2, 3, 1, 2, 3, 100};
        HashMap<Integer, Integer> expected = new HashMap<>();
        expected.put(1, 2);
        expected.put(2, 2);
        expected.put(3, 2);
        expected.put(100, 1);
        HashMap<Integer, Integer> actual = countOccur(numbers);
        assertEquals(expected, actual);
    }

This test will fail, of course (the previous test should still pass). Refer to Trushit's answer for one possible way to make it pass (requires Java 8 or later).

Solution 4:[4]

public class U7A1_NumOfOccurrInSevenInts {

    public static void main(String[] args) {
        System.out.print("Teacher's Copy");
        Scanner in = new Scanner(System.in);
        int[] arr = new int[7];
        System.out.print("Enter seven numbers: ");
        for (int i = 0; i < arr.length; ++i) {
            arr[i] = in.nextInt();  // read 7 numbers into array
        }
        for (int i = 0; i < arr.length; ++i) {   // go through all elements
            if (!checkIfElementAlreadyExists(arr, i)) {  // if this element did not already appear before in the array
                System.out.printf("Number %d occurs %d times.\n", arr[i],
                    count(arr, arr[i]));  // then print the number and the number of time it occurs in the array
            }
        }
    }

    public static int count(int[] arr, int num) {
        int count = 0;
        for (int i = 0; i < arr.length; ++i) {   // go through all elements in array
            if (arr[i] == num) { // if num is found, increase count
                count++;    // increment count
            }
        }
        return count;   // return the count of number of occurrences of num in array
    }

    public static boolean checkIfElementAlreadyExists(int[] arr, int index) {
        for (int i = 0; i < index; ++i) {    // go through all elements in array
            if (arr[i] == arr[index]) {  // if item in index already exists in the array
                return true;    // then return true
            }
        }
        return false;   // if element at index does not previously occur, then return false
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Trushit Shekhda
Solution 2
Solution 3 Alonso del Arte
Solution 4 Kai-Sheng Yang