Where does this program get its numbers from, and why is this caused by increasing 1 array size? (Java)

StackOverflow https://stackoverflow.com/questions/8335998

Question

This program simply is supposed to eliminate duplicates from an array. However, the second for loop in the eliminate method was throwing an out of bounds exception. I was looking and couldnt see how that could be, so I figured I would increase the array size by 1 so that I would get it to work with the only downside being an extra 0 tacked onto the end.

To my surprise, when I increased tracker[]'s size from 10 to 11, the program prints out every number from 0 to 9 even if I dont imput most of those numbers. Where do those numbers come from, and why am I having this problem?

import java.util.*;
class nodupes 
{
    public static void main(String[] args) 
    {   

        int[] dataset = new int[10];


        //getting the numbers
        for (int i = 0; i <= 9 ; i++)
        {
            Scanner input = new Scanner(System.in);
            System.out.println("Enter a one digit number");
            dataset[i] = input.nextInt();
        }

        int[] answer = (eliminateduplicates(dataset));
        System.out.println(Arrays.toString(answer));
    }

    public static int[] eliminateduplicates(int[] numbers)
    {

        boolean[] tracker = new boolean[11];
        int arraysize = 1; 
        for(int k = 0; k <= 9; k++)
        {

            if(tracker[numbers[k]] == false)
            {
                arraysize++;
                tracker[numbers[k]] = true;
            }

        }
        int[] singles = new int[arraysize];

        for(int l = 0; l <= arraysize; l++)
        {
            if(tracker[l] == true)
            {
                singles[l] = l;

            }


        }

        return singles;
    }
}    

The exception was occuring at this part

     if(tracker[l] == true)

but only when trackers size was 10. At 11 it just prints [0,1,2,3,4,5,6,7,8,9]

EDIT: The arraysize = 1 was a hold over from debugging, originally it was at 0

EDIT: Fixed it up, but now there is a 0 at the end, even though the array should be getting completely filled.

public static int[] eliminateduplicates(int[] numbers)
{

    boolean[] tracker = new boolean[10];
    int arraysize = 0; 

    for(int k = 0; k < numbers.length; k++)
    {

        if(tracker[numbers[k]] == false)
        {
            arraysize++;
            tracker[numbers[k]] = true;
        }

    }
    int[] singles = new int[arraysize];
    int counter = 0;

    for(int l = 0; l < arraysize; l++)
    {
        if(tracker[l] == true)
        {
            singles[counter] = l;
            counter++;
        }


    }

    return singles;
}
Was it helpful?

Solution

Edit like 20 because I should really be asleep. Realizing I probably just did your homework for you so I removed the code.

arraySize should start at 0, because you start with no numbers and begin to add to this size as you find duplicates. Assuming there was only 1 number repeated ten times, you would've created an array of size 2 to store 1 number. int arraysize = 0;

Your first for loop should loop through numbers, so it makes sense to use the length of numbers in the loop constraint. for( int i = 0; i < numbers.length; i ++)

For the second for loop: you need to traverse the entire tracker array, so might as well use the length for that (tracker.length). Fewer magic numbers is always a good thing. You also need another variables to keep track of your place in the singles array. If numbers was an array of 10 9s, then only tracker[9] would be true, but this should be placed in singles[0]. Again, bad job from me of explaining but it's hard without diagrams.

Derp derp, I feel like being nice/going to bed, so voila, the code I used (it worked the one time I tried to test it):

public static int[] eliminateduplicates(int[] numbers)
{
    boolean[] tracker = new boolean[10];
    int arraysize = 0; 

    for(int k = 0; k < numbers.length; k++)
    {
        if(tracker[numbers[k]] == false)
        {
            arraysize++;
            tracker[numbers[k]] = true;
        }
    }

    int[] singles = new int[arraysize];

    for(int l = 0, count = 0; l < tracker.length; l++)
    {
        if(tracker[l] == true)
        {
            singles[count++] = l;
        }
    }

    return singles;
}

OTHER TIPS

Since arrays start at 0, your arraysize will be one larger than the number of unique numbers, so your final loop goes through one too many times. In other words "l" (letter l -- try using a different variable name) will get to 11 if you have 10 unique numbers and tracker only has item 0-10, thus an out of bounds exception. Try changing the declaration to int arraysize = 0;

Once again defeated by <=

for(int l = 0; l <= arraysize; l++)

An array size of 10 means 0-9, this loop will go 0-10

For where the numbers are coming from,

singles[l] = l;

is assigning the count values into singles fields, so singles[1] is assigned 1, etc.

I feel you are doing too much of processing for getting a no duplicate, if you dont have the restriction of not using Collections then you can try this

public class NoDupes {
    public static void main(String[] args) {
        Integer[] dataset = new Integer[10];
        for (int i = 0; i < 10; i++) {
          Scanner input = new Scanner(System.in);
          System.out.println("Enter a one digit number");
          dataset[i] = input.nextInt();
        }
        Integer[] arr = eliminateduplicates(dataset);
        for (Integer integer : arr) {
           System.out.println(integer);
        }
    }

     public static Integer[] eliminateduplicates(Integer[] numbers) {
        return new HashSet<Integer>(Arrays.asList(numbers)).toArray(new Integer[]{});
     }
}

To answer your question your final loop is going one index more than the size.

The range of valid indexes in an array in Java is [0, SIZE), ie. from 0 up to arraysize-1.

The reason you're getting the exception is because in your loop you're iterating from 0 to arraysize inclusively, 1 index too far:

for(int l = 0; l <= arraysize; l++)

Therefore when you get to if(tracker[l] == true) in the last iteration, l will equal arraysize and tracker[l] will be outside the bounds of the array. You can easily fix this by changing <= to < in your for loop condition.


The reason that the problem goes away when the size of your array is changed from 10 to 11 has to do with arraysize being incremented up to 10 in the for loop above the one causing the problems. This time, singles[10] is a valid element in the array since the range of indexes in your array is now [0, 11).

EDIT: Actually arraysize has the potential to be incremented to 11, I thought it was initialised to 0 in which case it would only get to 10. Either way the above is still valid; the last index you try and access in your array must be 1 less than the length of your array in order to avoid the exception you're getting, since arrays are zero-based. So yeah, long story short, <= should be <.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top