4

I came across this Java program and its behaving in unexpected way. The following program computes the differences between pairs of elements in an int array.

import java.util.*;

public class SetTest
{
       public static void main(String[] args)
       {
            int vals[] = {786,678,567,456,
                          345,234,123,012};

            Set<Integer> diffs = new HashSet<Integer>();

            for(int i=0; i < vals.length ; i++)
                for(int j = i; j < vals.length; j++)
                       diffs.add(vals[i] - vals[j]);

            System.out.print(diffs.size());
       }
}

If we analyze it seems set size should be 8 which is the size of the array. But if you ran this program it prints 14. What's going on? Any idea?

Thank you in advance.

Answer: This strange behavior happens because 012 in the array becomes octal if we change it to 12 then it prints 8 as expected.

Lesson: Never pad an integer literal with zeros.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Umesh K
  • 13,436
  • 25
  • 87
  • 129

6 Answers6

11

Did you noticed that 012 (octal) is 10 (decimal) ?

PeterMmm
  • 24,152
  • 13
  • 73
  • 111
3

If we analyze it seems set size should be 8 which is the size of the array. But if you ran this program it prints 14. What's going on? Any idea?

Just trace info

1   : 786 - 786 = 0 (new one 1 )
2   : 786 - 678 = 108   (new one 2 )
3   : 786 - 567 = 219   (new one 3 )
4   : 786 - 456 = 330   (new one 4 )
5   : 786 - 345 = 441   (new one 5 )
6   : 786 - 234 = 552   (new one 6 )
7   : 786 - 123 = 663   (new one 7 )
8   : 786 - 10 = 776    (new one 8 )
9   : 678 - 678 = 0 (already contained)
10  : 678 - 567 = 111   (new one 9 )
11  : 678 - 456 = 222   (new one 10 )
12  : 678 - 345 = 333   (new one 11 )
13  : 678 - 234 = 444   (new one 12 )
14  : 678 - 123 = 555   (new one 13 )
15  : 678 - 10 = 668    (new one 14 )
16  : 567 - 567 = 0 (already contained)
17  : 567 - 456 = 111   (already contained)
18  : 567 - 345 = 222   (already contained)
19  : 567 - 234 = 333   (already contained)
20  : 567 - 123 = 444   (already contained)
21  : 567 - 10 = 557    (new one 15 )
22  : 456 - 456 = 0 (already contained)
23  : 456 - 345 = 111   (already contained)
24  : 456 - 234 = 222   (already contained)
25  : 456 - 123 = 333   (already contained)
26  : 456 - 10 = 446    (new one 16 )
27  : 345 - 345 = 0 (already contained)
28  : 345 - 234 = 111   (already contained)
29  : 345 - 123 = 222   (already contained)
30  : 345 - 10 = 335    (new one 17 )
31  : 234 - 234 = 0 (already contained)
32  : 234 - 123 = 111   (already contained)
33  : 234 - 10 = 224    (new one 18 )
34  : 123 - 123 = 0 (already contained)
35  : 123 - 10 = 113    (new one 19 )
36  : 10 - 10 = 0   (already contained)

Also, debugger is a great thing in cases when you can't analyze program's behavior ;)

Stan Kurilin
  • 15,614
  • 21
  • 81
  • 132
3

Since you are running two nested loops the add() method is called multiple times. Since a set cannot contain duplicate objects the number of values in the set will be the number of unique values. The add() function returns true if the set did not already contain the element and false if the set already had the element.

Change the line

diffs.add(vals[i] - vals[j]);

to

System.out.println((diffs.add(vals[i] - vals[j])));

to see what I mean.

Rich
  • 15,602
  • 15
  • 79
  • 126
Can't Tell
  • 194
  • 1
  • 5
  • +1 for being the only one to cover the fact that a Set allows each value only once && that the loops are nested. – Rich Mar 07 '11 at 13:56
-1

For a set of 8 elements, there are 36 (8 + 7 + ... + 1) distinct pairs (if one ignores the order of elements in the pairs). So diffs may contain up to 36 elements. But apparently, some differences occur multiple times, e.g. 456-345 = 111 and 345-234 = 111. As a set can only contain each value at most once, only the 14 distinct differences remain.

Lars Noschinski
  • 3,667
  • 16
  • 29
-1

Your HashSet only stores non-duplicated values. If you want duplicates, you have to use a different set type. The size of diffs should be 36 with duplicates; I get a size of 19 when I run the code as-is (19 unique different values).

John
  • 727
  • 5
  • 15
-1

It actually prints out 19 here...

You have 36 calculations out of which 17 have an identical result. The HashSet only keeps unique values, this is why we don't have a size of 36 but a size of 19 ...

Vincent Mimoun-Prat
  • 28,208
  • 16
  • 81
  • 124