0

I made a program that counts the elements in an array. It works but there is a sort of error in my program.

I want the output of my program is like this:
1 occured: 2times
2 occured: 1times
3 occured: 1times
6 occured: 1times

but my program gives an output of this:
1 occured: 1times
1 occured: 2times
2 occured: 1times
3 occured: 1times
6 occured: 1times

String[] values= {"1", "1", "3", "6", "2"};
int[] counts = new int[values.length]; 
Arrays.sort(values);
int temp = 0;
int c = 0;
for(int i = 0; i < values.length; i++){
  counts[i] = Integer.parseInt(values[i]);
  for(int j = 0;j < counts.length; j++) {
    if(counts[i] == counts[j]) {
      c++;
    }
  }
  System.out.println(counts[i] + " occured: " + c +" times");
  c = 0;
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
Dio Baccay
  • 83
  • 8

4 Answers4

1

Here's the problem: you want only four print statements to occur, but you're getting five. Because this code is missing curly braces and has bad indentations, you may or may not see that the println function belongs to the i loop. How many times is the i loop going to run? Hint: it's i.length, which in this case equals __ (you fill in the blank).

Once you see why there's an extra println, try fixing your code, then come back with specific questions if you need help.

musical_coder
  • 3,886
  • 3
  • 15
  • 18
1

Look, similar to your approach but using only one array (and without hashmaps). I tested and it works.

     String[] values= {"1","1","3","6","2"};     
     Arrays.sort(values);
     int c=1,i=0;
     while(i<values.length-1){
         while(values[i].equals(values[i+1])){
             c++; 
             i++;   
         }   
         System.out.println(values[i] + " appeared " + c + " times");            
         c=1;
         i++;
         if(i==values.length-1)
             System.out.println(values[i] + " appeared " + c + " times");
     }  
bogdan.herti
  • 1,110
  • 2
  • 9
  • 18
  • 1
    That's quite awful, really: the reason the `values[i]==values[i+1]` even works is that compiler interns string literals. Try reading the `values` from user's input to see this break into pieces. The logic to force printing the last item inside the loop is so convoluted that it makes my brain hurt. I understand that you took OP's approach as your starting point, so I would not downvote this, but I think a fix-up like that may teach the OP a completely wrong point. – Sergey Kalinichenko Sep 26 '13 at 15:22
1

Your code is too fast at printing its decision: rather than making one println per item of values, you need to call it once per distinct item found in the values array.

One way of doing it would be by using a Map<String,Integer> to count the items. You can do it like this:

Map<String,Integer> counts = new HashMap<String,Integer>();
for (String s : values) {
    if (counts.containsKey(s)) {
        int old = counts.get(s);
        counts.put(s, old+1);
    } else {
        counts.put(s, 1);
    }
}
for (Map.Entry<String,Integer> entry : counts.entrySet()) {
    System.out.println(entry.getKey() + " - " + entry.getValue());
}

Demo on ideone.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

Apache's CollectionUtils has a built-in utility method similar to dasblinkenlight's approach:

Map<String, Integer> counts = 
    CollectionsUtils.getCardinalityMap(Arrays.asList(values));
for (Map.MapEntry<String,Integer> entry : counts) {
    System.out.println(entry.getKey() + " - " + entry.getValue());
}

EDIT:
Updating old answers. Java 8 streams have a built-in equivalent for this:

Map<Stirng, Long> = 
    Arrays.stream(values)
          .collect(Collectors.groupingBy(Function.identity(), 
                   Collectors.counting()));
Mureinik
  • 297,002
  • 52
  • 306
  • 350