0

I am having trouble finding the most and least used String in an ArrayList. The program should go through a file of Strings and count how many multiple strings there are in the list. Then print the least and most used name in the list. The ArrayList Part is finished. It is just finding the most and least common name I am having trouble with. I have no idea how to even start with it. This is what I have found online but it is not working.

Map<String, Integer> dogNames = new HashMap<>();
for (Dog dog : dogs) {
    Integer value = dogNames.get(dog);
    if (value == null) {
        value = 0;
    }
    value++;
    dogNames.put(dog.getName(), value);
}

int leastCommon = Integer.MAX_VALUE;
String leastCommonName = null;
for (String name : dogNames.keySet()) {
    int value = dogNames.get(name);
    if (value < leastCommon) {
        leastCommon = value;
        leastCommonName = name;
    }
}

System.out.println("Least common (" + leastCommon + ") is " + leastCommonName);
AstroCB
  • 12,337
  • 20
  • 57
  • 73
  • You can also check this out http://stackoverflow.com/questions/5211194/count-occurences-of-words-in-arraylist – Rika Sep 11 '14 at 18:17

2 Answers2

1

The problem with your code seems to be in this line:

Integer value = dogNames.get(dog);

Your map holds dog names (String), but you are getting the entry for the Dog, which does not exist! Thus, value stays 0 even if you've seen that name before. If you fix this, you code should work.


Instead of your loop for searching the least common name, you could also define a custom Comparator based on the counts in the map and then use Collections.min and Collections.max:

Comparator<Dog> comp = new Comparator<Dog>() {
    @Override
    public int compare(Dog o1, Dog o2) {
        return Integer.compare(dogNames.get(o1.getName()), dogNames.get(o2.getName()));
    }
};
System.out.println("least " + Collections.min(dogs, comp));
System.out.println("most  " + Collections.max(dogs, comp));

With Java 8, you can make it even shorter, using Comparator.comparing:

List<Dog> dogs = ...
Map<String, Integer> dogNames = new HashMap<>();
dogs.forEach(dog -> dogNames.put(dog.getName(), dogNames.getOrDefault(dog.getName(), 0) + 1));

Comparator<Dog> comp = Comparator.comparing(d -> dogNames.get(d.getName()));
System.out.println("least " + Collections.min(dogs, comp));
System.out.println("most  " + Collections.max(dogs, comp));

Or even shorter, using Collections.frequency instead of building your own map, and using that to compare. Note, however, that this will be wasteful if the list is very long, since this will search the list each time anew instead of caching the counts in the map.

List<Dog> dogs = ...
Comparator<Dog> comp = Comparator.comparing(d -> Collections.frequency(dogs, d.getName()));
System.out.println("least " + Collections.min(dogs, comp));
System.out.println("most  " + Collections.max(dogs, comp));
tobias_k
  • 81,265
  • 12
  • 120
  • 179
0

Your code should look something like this...

Map<String,int> frequencyOfDogNames = new HashMap<String,int>();
for(String dogName:dogNames) {
    if(frequencyOfDogNames.contains(dogName)) {
         continue;
    }
    frequencyOfDogNames.put(dogName, Collections.frequency(dogs, "dogName")); 
}

This will give you the map of all the names with the occurrences.

Now we should loop thought the map to see which one are the max and min...

int leastCommon = Integer.MAX_VALUE;
int mostCommon = 0;
String leastCommonName, mostCommonName;
int occurrence;
for(String dogName: frequencyOfDogNames.keySet()) {
    occurrence  = frequencyOfDogNames.get(dogName);
    if(leastCommon > occurrence){
         leastCommon = occurrence;
         leastCommonName = dogName;
    }
    if(mostCommon < occurrence){
         mostCommon = occurrence;
         mostCommonName = dogName;
    }
}
StackFlowed
  • 6,664
  • 1
  • 29
  • 45