public class IntegerSet {
int dMax;
boolean[] set;
public IntegerSet(int domainMax) {
dMax = domainMax + 1;
set = new boolean[dMax];
}
...some methods...
public static IntegerSet union(IntegerSet s1, IntegerSet s2) {
IntegerSet union = new IntegerSet(Math.max(s1.dMax, s2.dMax));
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
union.set[i] = (s1.set[i] || s2.set[i]);
}
return union;
}
Can anyone tell me whats wrong with this?
I can't understand why I'm getting the error message after hours: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6
As the two sets supplied as arguments may have different domain max; the resulting union should have whichever of these two domain max is larger hence why I am using Math.max.
Any help would be appreciated.
This:
dMax = domainMax + 1;
should be:
dMax = domainMax;
Or just use set.length
.
Your for-loop goes from 0
to the max size of s1
and s2
. But because (in the situation that throws errors), one of your IntegerSet
s is smaller, the for-loop goes past the size of the smaller IntegerSet
when retrieving all of the boolean
s from the larger IntegerSet
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
union.set[i] = (s1.set[i] || s2.set[i]);
}
If the size of one set is smaller than the max, then you are going to get an IndexOutOfBoundsException
.
Example:
Say you have the following conditions:
s1 = {0, 1, 1, 0, 1}
s2 = {0, 0, 0}
s1.dMax = 5, so s1.set has a size of 5
s2.dMax = 3, so s2.set has a size of 3
In your for-loop, you are going to iterate from 0 to 4. When the following occurs:
i = 3
s1.set[i] = s1.set[3] //IndexOutOfBoundsException because the size of s1.set is 3.
You have a couple options of how you can fix this:
IndexOutOfBoundsException
for your smaller IntegerSet
and just set the index in union
to the boolean
value of your larger set. IntegerSet
depending on what you want the union to be for the blank indicies. min
size of the two IntegerSet
s if you want to ignore the extra boolean
s (Judging from the fact that you made the union set the size of the max, I am guess that is not the case) Side Note: You also do not need to add the +1
to the dMax
variable when you create your union
IntegerSet
. That is going to result in your having an extra index that you don't need and could cause problems later.
The problem arises when s1
and s2
have different lengths. These lines are flawed:
IntegerSet union = new IntegerSet(Math.max(s1.dMax, s2.dMax));
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
Think about what two sets of unequal length look like: (using 1 and 0 in place of true
and false
)
s1: {0 1 0 0 1 1} length = 6
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
You've programmed your loop to iterate from 0 up to the maximum length of the two sets, which in the above example is 12 (meaning that the last value your loop will use is 11). But s1
is only 6 elements long--its last valid index is 5! As the loop erroneously attempts to access elements 7 through 12 (indices 6 through 11) of s1
, it throws an ArrayIndexOutOfBoundsException.
To fix this, you should use the minimum length of the two sets in both of the lines where you use the maximum. This way, you will be taking the union:
s1: {0 1 0 0 1 1} length = 6
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
union: {1 1 1 0 1 1} length = min(6, 12) = 6
Instead of
s1: {0 1 0 0 1 1}! ! ! ! ! ! length = 6; no elements 7 through 12!
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
union: {1 1 1 0 1 1 ! ! ! ! ! !} length = max(6, 12) = 12 -> errors
This leaves the later section of s2
out of the union, as there are no corresponding elements in s1
to perform a boolean ||
with. However, you could also do something like this:
IntegerSet union = new IntegerSet(Math.max(s1.dMax, s2.dMax));
for (int i = 0; i < (Math.max(s1.dMax, s2.dMax)); i++) {
if (s2.set.length > s1.set.length)
{
union.set[i] = s2.set[i] || (i < s1.set.length ? s1.set[i] : false);
}
else
{
union.set[i] = s1.set[i] || (i < s2.set.length ? s2.set[i] : false);
}
}
This will use false
's for every missing element in the shorter set, resulting in the union being:
s1: {0 1 0 0 1 1} length = 6
s2: {1 1 1 0 0 0 1 0 1 1 0 1} length = 12
union: {1 1 1 0 1 1 1 0 1 1 0 1} length = max(6, 12) = 12
All entries are simply copied from the longer set, since anything || false
anything || false
is itself.
You are using dMax
as the number of boolean array
elements in one place, and as the domain maximum (wrong) when you create the new union
set. (That causes you to make union
1 element too large.)
Several things to consider when you rewrite your code:
domainMax
implies a set of integers from [0, domainMax], do define a boolean array with domainMax+1
elements (don't bother with a dMax variable, you can get that info by checking set.length
union
" function, be sure to handle the case where one or both of the input IntegerSet
s is null protected set
to make sure the internal representation of the IntegerSet
is not known or accessed outside your class IntegerSet
s, only perform the or operation (||) for the case where both sets have values; then for the "bigger" set, simply copy over the remaining items.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.