4

I'm trying to make an implementation of 'adding' the elements of two arrays in Java. I have two arrays which contain integers and i wanna add them. I dont want to use immutable variables. I prefer do sth like that : a.plus(b); The problem is when i add 2 arrays with different length.It tries to add the elements of b to a, but if b has a bigger length it flags an error "ArrayIndexOutOfBoundsException". I can understand why that's happening. But how can i solve this? How can i expand array a? :/

public void plus(int[] b)
    {

        int maxlength = Math.max( this.length, b.length );

        if (maxlength==a.length)
        {
            for (int i = 0; i <= maxlength; i++)
            {
                a[i] = a[i] + b[i];   //ArrayIndexOutOfBoundsException error
            }
        }
    }
Mat
  • 202,337
  • 40
  • 393
  • 406
FILIaS
  • 495
  • 4
  • 13
  • 26
  • Either someone has snuck operator overloading into Java while I wasn't looking, or this code isn't right - a is a variable of type `Polynomial` which is a user defined class, but you're using `a[i]`. – Pete Kirkham Nov 13 '10 at 18:41
  • possible duplicate of [What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?](http://stackoverflow.com/questions/5554734/what-causes-a-java-lang-arrayindexoutofboundsexception-and-how-do-i-prevent-it) – Raedwald Mar 12 '15 at 14:07

5 Answers5

8

i <= maxlength replace this with i < maxlength.

Your array index is starting at zero, not at one. So the length of the array is one less than the end index of the array. When you use <= you are trying to go one element after the last element in your array, Hence the exception.

Also you got to check the length of array b. If length of array b is smaller than a, you will end up facing the same exception.

int maxlength = Math.min( this.length, b.length ); is more appropriate.

Or incase if you don't want to miss out any elements in either of the arrays while adding, ArrayList is the answer for you. ArrayList is the self expanding array you are looking for. Here is how you can do that -

    // First ArrayList
    ArrayList<Integer> a = new ArrayList<Integer>();
    a.add(1);
    a.add(2);
    a.add(3);

    // Second ArrayList
    ArrayList<Integer> b = new ArrayList<Integer>();
    b.add(1);
    b.add(2);
    b.add(3);
    b.add(4);

    int maxlength = Math.max(a.size(), b.size());
    // Add the elements and put them in the first ArrayList in the corresponding 
    // position
    for (int i = 0; i < maxlength; i++) {
        if (i < a.size()) {
            if (i < b.size()) {
                int j = a.get(i);                   
                a.set(i, j + b.get(i));
            }
        } else {
            a.add(i, b.get(i));
        }
    }

    for (int j : a) {
        System.out.println(j);
    }
Johnbabu Koppolu
  • 3,212
  • 2
  • 22
  • 34
  • 1
    Just trying to check that..it doesnt add the last element of b if its bigger than a. – FILIaS Nov 13 '10 at 18:39
  • EDIT: i also tried to use min,but then how can i add the rest elements of the bigger array? that;s why i asked about expanding arrays – FILIaS Nov 13 '10 at 18:47
  • @FILIaS - You can't do that ...Right now you are assigning the added values back to a. If 'b' is bigger than 'a' and you want add up last elements in b...where will you store them? I suggest you use ArrayList instead of array for your case. – Johnbabu Koppolu Nov 13 '10 at 18:55
  • @FILIaS - Working on a generic solution using ArrayList, will be back soon. – Johnbabu Koppolu Nov 13 '10 at 19:04
  • @FILIaS - Gave a code snippet, it adds up the elements irrespective of the lengths of a & b. – Johnbabu Koppolu Nov 13 '10 at 19:30
  • @johnbk thank u very much. Im just thinking how i can 'put' an int array into a list. as im getting the array ready from a parameter in varargs. :/ – FILIaS Nov 13 '10 at 19:33
  • @FILIaS - If your varargs parameter is of type Integer, then you can do this - ArrayList al = new ArrayList(Arrays.asList(varargsparam)); – Johnbabu Koppolu Nov 13 '10 at 19:59
  • @FILIaS - Or if your varargs parameter is of type primitive int , then you got no other way than looping through all the elements as you do for an array and adding them to the list one by one. – Johnbabu Koppolu Nov 13 '10 at 20:01
  • @johnbk - using `remove(i)` and then `add(i)` is performance costly for large ArrayLists. The `remove(i)` will move/copy the values after index `i` in the backing array forward and then `add(i)` move/copy them backward again. This will happen over each pass. Try `set(i, value)` instead. – Bert F Nov 13 '10 at 20:36
3

How can i expand array a?

Don't use arrays if you need variable-size data structures. Use Lists.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • I've thougth about that,the problem is that i get the array as an parameter in a method using varargs. Like: getArray(int...arrayA) {...} so i dont know how can i transfer an int array to a linkedList – FILIaS Nov 13 '10 at 19:21
  • @FILIaS: [Arrays.asList()](http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html#asList\(T...\)), or just write your own (it is **not** hard) – Matt Ball Nov 13 '10 at 19:25
  • I don't think it is that easy for primitive arrays. – Johnbabu Koppolu Nov 13 '10 at 20:11
  • Exactly! I was referring to your advice on using Arrays.asList() in case of primitive array, when the OP's varargs parameter is of type 'int' – Johnbabu Koppolu Nov 13 '10 at 21:34
2

maxlength is the max between the size of a[] and b[], so in a loop from 0 to maxlength, you will get an ArrayIndexOutOfBoundsException when i exceeds the min of the size of a[] and b[].

Try this:

public void plus(int[] b)
    {
        Polynomial a = this;
        int[] c;
        int maxlength;
        if (a.length>b.length) {
            c=a;
            maxlength=a.length;
        } else {
            c=b;
            maxlength=b.length;
        }

        int ca, cb;
        for (int i = 0; i < maxlength; i++)
        {
            if (i<this.length)
                ca=a[i];
            else
                ca=0;
            if (i<b.length)
                cb=b[i];
            else
                cb=0;
            c[i] = ca + cb;
        }
    }
Alexis Dufrenoy
  • 11,784
  • 12
  • 82
  • 124
  • I have done it properly using another *helping* array.But i dont want to do it like that. i just want to alter array a. thanx – FILIaS Nov 13 '10 at 18:51
  • I changed it so c is only a reference to a or b. – Alexis Dufrenoy Nov 13 '10 at 18:56
  • but even now,u dont alter a array. – FILIaS Nov 13 '10 at 19:15
  • Yes, I alter one. For example, if a is the longest array, c will be a reference to the same array, and this array will be changed at each loop. It's only shorter to write. You can write it with a condition instead of the line c[i] = ca + cb;, but it would only be longer and more complicated, for the same result. – Alexis Dufrenoy Nov 13 '10 at 19:25
  • hm i think this: if (maxlength==a.Length) doesnt need right? Also on this: cb=b[0]; do u mean cb=b[i]; ? – FILIaS Nov 13 '10 at 19:30
  • Oh, yeah, right. That's a typing error. I corrected it. And yes, the if (maxlength==a.Length) part is not useful. – Alexis Dufrenoy Nov 13 '10 at 19:33
  • @Traroth. Thank you very much. And sorry for the many questions.But i still cant get how array a changes... :/ – FILIaS Nov 13 '10 at 19:39
  • @Traroth. Ive tried to do it like that. Array a doesnt change so when i call a.plus(b) and then printing a its still the same as before method plus :( – FILIaS Nov 13 '10 at 19:47
  • a and b are references to arrays. So if you write c=a, you are creating a copy of the reference, and not of the actual array. So in the code I posted, c is a reference to the longest array between a and b. Which means it's not every time a which changes, but a or b. The longest from the two. – Alexis Dufrenoy Nov 13 '10 at 19:47
2

How about this:

private int[] a;

/**
 * Adds the specified array to our array, element by element, i.e.
 * for index i, a[i] = a[i] + b[i].  If the incoming array is
 * longer, we pad our array with 0's to match the length of b[].
 * If our array is longer, then only the first [b.length] values
 * of our array have b[] values added to them (which is the same
 * as if b[] were padded with 0's to match the length of a[]. 
 *
 * @param b the array to add, may not be null
 */
public void plus(final int[] b)
{
    assert b != null; 

    if (a.length < b.length) {
        // Expand a to match b
        // Have to move a to a larger array, no way to increase its
        // length "dynamically", i.e. in place.
        final int[] newA = new int[b.length];
        System.arraycopy(a, 0, newA, 0, a.length);
        // remaining new elements of newA default to 0
        a = newA;
    }

    for (int i = 0; i < b.length; i++)
    {
        a[i] = a[i] + b[i];
    }
}

Another version:

private ArrayList<Integer> aList;

public void plusList(final int[] b)
{
    assert b != null; 

    if (aList.size() < b.length) {
        aList.ensureCapacity(b.length);
    }

    for (int i = 0; i < b.length; i++)
    {
        if (i < aList.size()) {
            aList.set(i, aList.get(i) + b[i]);
        } else {
            aList.add(b[i]);
        }
    }
}

Edit: Here's the full class with sample run from data in comments

public class AddableArray {
    private int[] a;

    public AddableArray(final int... a) {
        this.a = a;
    }

    /**
     * Adds the specified array to our array, element by element, i.e.
     * for index i, a[i] = a[i] + b[i].  If the incoming array is
     * longer, we pad our array with 0's to match the length of b[].
     * If our array is longer, then only the first [b.length] values
     * of our array have b[] values added to them (which is the same
     * as if b[] were padded with 0's to match the length of a[].
     *
     * @param b the array to add, may not be null
     */
    public void plus(final int[] b)
    {
        assert b != null;

        if (a.length < b.length) {
            // Expand a to match b
            // Have to move a to a larger array, no way to increase its
            // length "dynamically", i.e. in place.
            final int[] newA = new int[b.length];
            System.arraycopy(a, 0, newA, 0, a.length);
            // remaining new elements of newA default to 0
            a = newA;
        }

        for (int i = 0; i < b.length; i++)
        {
            a[i] = a[i] + b[i];
        }
    }

    int[] get() {
        return a;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("a[] = [ ");
        for (int i = 0; i < a.length; i++) {
            if (i > 0)   sb.append(", ");
            sb.append(a[i]);
        }
        sb.append(" ]");
        return sb.toString();
    }

    public static void main (final String[] args) {

        final AddableArray myAddableArray = new AddableArray(1,2,3);

        System.out.println("Elements before plus(): ");
        System.out.println(myAddableArray.toString());

        final int b[]={1,2,3,4};
        myAddableArray.plus(b);

        System.out.println("Elements after plus(): ");
        System.out.println(myAddableArray.toString());

    }
}

Sample run:

Elements before plus(): 
a[] = [ 1, 2, 3 ]
Elements after plus(): 
a[] = [ 2, 4, 6, 4 ]
Bert F
  • 85,407
  • 12
  • 106
  • 123
  • Thank u very much BertF! on this: System.arraycopy(a, 0, newA, 0, a.length); would u say better System.arraycopy(a,0,newA,0,b.length); ?? If i understood well,thats what u mean,right? – FILIaS Nov 13 '10 at 21:41
  • No, a.length is correct. We want to create a new array `newA` that is `b.length` long, but we want to copy the old `a[]` data (there is exact `a.length` items in `a[]`) to the first `a.length` spaces of the new array `newA`. – Bert F Nov 13 '10 at 21:49
  • aha ok im fine! another note pls, on the line: for (int i = 0; i < b.length; i++) why do u use b.length instead of maxlength? – FILIaS Nov 13 '10 at 21:55
  • I only want to add together elements that exist in both arrays, i.e. min(a.length, b.length). Think about some examples: `a[] = {1, 2, 3}}, `b[] = {1, 2}` - I only want to add together 2 (`min(2,3)`) of the values (because `b` has no 3rd value. How about if `a[] = {1, 2, 3}}, `b[] = {1, 2, 3, 4}` - I only want to add together 3 (`min(3, 4`) of the values (because `a` has no 4th value. However, I already ensured that `(a.length >= b.length)` (if `a` was shorter before, then the `if` code already made it longer). So, when `(a.length >= b.length)`, then `min(a.length, b.length) == b.length`. – Bert F Nov 13 '10 at 22:05
  • testing my code with this i get: if a[]={1,2,3} , b[]={1,2,3,4}... a+b={2,4,6} :/ the correct shouldnt be {2,4,6,4} ? – FILIaS Nov 13 '10 at 22:33
  • The above code works fine with my test and, when I tried it with your example, it produce the correct answer ([2,4,6,4]). Are you sure you are looking at all of `a[]`? The only thing I can think of is that your question code refers to a `this.length` and `a.length`. The answer code only updates `a` (implicitly updating `a.length`), but it does not update `this.length`. So `this.length` has the old length and printing `a[]` with the old length wouldn't show all of the new `a[]`. Without know more about the your test code (and possibly this Polynomial class referred to by the comments). – Bert F Nov 14 '10 at 05:10
  • what about using on the all code this.length? Shouldnt be right? But it still doesnt print the {2,4,6,4} instead of {2,4,6} :/ – FILIaS Nov 14 '10 at 10:43
  • EDIT: sorry i found my mistake on my code. Thanx for your help! ;) – FILIaS Nov 14 '10 at 11:47
1

Try replacing:

for (int i = 0; i <= maxlength; i++)

with:

for (int i = 0; i < maxlength; i++)
Nico Huysamen
  • 10,217
  • 9
  • 62
  • 88