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. I have tried asking but I got it in HashMap form. I kind of tried to figure it out but this is all I could think of.

for (int i = 0; i< dogs.size(); i++)
if dogs.get(0).getName().equals dogs.get(i).getName();
{
   dogs.get(i).getName()++;    
 }
2
  • 3
    Why are you averse to using a HashMap? Commented Sep 11, 2014 at 11:42
  • Don't be afraid to go back and rethink what you've already done. It sounds like you're starting from a text file, rather than being given an ArrayList; really what this means is that an ArrayList was the wrong choice of data structure in the first place. Sometimes the best route to your destination involves reversing a little and starting again on the right road. Commented Sep 11, 2014 at 11:51

3 Answers 3

2

You could sort the list first and then count the amount of same consecutive names. Then only keep the smallest and the largest number..

ofcource hashmaps are ideal for this kind of problem and unless there is a really good reason why you can't use one you should use a hashmap for this

Sign up to request clarification or add additional context in comments.

1 Comment

This is definitely the best way to do it given the constraints as described in the question. But it's not as good as rethinking the question.
0

You can use frequency()

Eg:

 List<String> myList=new ArrayList<>();
 myList.add("a");
 myList.add("b");
 myList.add("a");
  for(String i:new HashSet<>(myList)){
     System.out.println(i+" has "+Collections.frequency(myList,i)+" times ");
  }

Out put:

 b has 1 times 
 a has 2 times 

You can apply this to find most and lowest occurrence.

Or you can use HashMap.

  List<String> myList = new ArrayList<>();
  myList.add("a");
  myList.add("b");
  myList.add("a");
    Map<String, Integer> map = new HashMap<>();
    for (String i : new HashSet<>(myList)) {
        Integer val = map.get(i);
        if (val != null) {
            map.put(i, val + 1);
        } else {
            map.put(i, 1);
        }
    } 

You will get all occurrences as value for any String

1 Comment

The first one is quadratic in the length of the list, though. Enermis' solution is O(n log n) for the sort, and then a linear pass to read off frequencies. Your HashMap solution is linear, but OP is allergic to HashMaps...
0

This is how you would solve your problem by relying on Java Streams API:

final SortedSet<Entry<String, Long>> s =
    lineList.stream().collect(groupingBy(identity(), counting())).entrySet()
    .stream().collect(toCollection(()->new TreeSet<>(comparing(Entry::getValue))));
System.out.println(s.first() + ", " + s.last());

Or, if you can start over from the point where you read the file, this would be better because it skips the step where you first create a list of lines and goes directly to constructing the frequency map:

try (BufferedReader r = Files.newBufferedReader(Paths.get("input.txt"))) {
  final SortedSet<Entry<String, Long>> s =
      r.lines().collect(groupingBy(identity(), counting())).entrySet().stream()
      .collect(toCollection(()->new TreeSet<>(comparing(Entry::getValue))));
  System.out.println(s.first() + ", " + s.last());
}

Note: this is the list of static imports needed by the above code:

import static java.util.Comparator.comparing;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toCollection;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.