4

I want to rank in java an ArrayList<String> with the number of times that the String appears. Like this: if I have an

ArrayList<String>= [French, English, German, French, French, Belgium, English, Belgium]

I count the number that "French", "English", "Belgium",etc. appear. So French appear 3 times, English 2 times, Belgium 2 times, German one times. Then I want to rank the ArrayList<String> in function of the number.

The result will be:

French 3
English 2 
Belgium 2
German 1

How I can do this? How to associate an integer and a String?

Alex K
  • 8,269
  • 9
  • 39
  • 57
user51324
  • 59
  • 1
  • 6
  • possible duplicate of [Looking to associate strings to ints in a cleaner/more efficient way](http://stackoverflow.com/questions/5698150/looking-to-associate-strings-to-ints-in-a-cleaner-more-efficient-way) – BackSlash Jun 09 '14 at 11:13
  • Parse the arrayList and create a map with "language" as key and "count" as value.. – TheLostMind Jun 09 '14 at 11:14

3 Answers3

6

Don't reinvent the wheel and use the frequency method of the Collections class:

public static int frequency(Collection<?> c, Object o)

Returns the number of elements in the specified collection equal to the specified object. More formally, returns the number of elements e in the collection such that (o == null ? e == null : o.equals(e)).

If you need to count the occurrences for all elements, use a Map and loop cleverly :) Or put your list in a Set and loop on each element of the set with the frequency method above. HTH

EDIT / Java 8: If you fancy a more functional, Java 8 one-liner solution with lambdas, try:

Map<String, Long> occurrences = 
  list.stream().collect(Collectors.groupingBy(w -> w, Collectors.counting()));

And then sort the map by value.

VH-NZZ
  • 5,248
  • 4
  • 31
  • 47
  • 1
    I wouldn't upvote for the `frequency` comment, since it still requires that the coder iterate over the `List` and store/associate the values somehow. But +1 for sick Java 8 skills. :) – asteri Jun 09 '14 at 11:18
  • I don't understand your answer... When I try .stream() on my list this method doesn't exist... – user51324 Jun 09 '14 at 16:46
  • @momo70 Upgrade to Java 8 and enjoy functional interfaces! is there anything else that you don't understand? – VH-NZZ Jun 10 '14 at 18:31
  • I found a solution [here](http://javarevisited.blogspot.fr/2012/12/how-to-sort-hashmap-java-by-key-and-value.html) But @okiharaherbst what is `w -> w`? – user51324 Jun 10 '14 at 22:31
  • @momo70,`w -> w` is called a _lambda expression_, and has been introduced to Java in its 8th release to bring some _functional programming_ constructs to the language. Have a look at http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html and http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html if you're interested and need a primer on the topic. HTH. – VH-NZZ Jun 10 '14 at 23:46
2

Any time you need to associate data, you should be thinking Map all the way. HashMap is the basic class used for this. So you can iterate over your list and create your associations in a Map<String, Integer>.

List<String> stuff = new ArrayList<String>();
// ...populate it

Map<String, Integer> map = new HashMap<String, Integer>();    
for(String string : stuff) {
    if(map.containsKey(string)) {
        map.put(string, map.get(string) + 1);
    }
    else {
        map.put(string, 1);
    }
}

Check out the full HashMap API here.

asteri
  • 11,402
  • 13
  • 60
  • 84
  • Thank you, that's what I was looking for. But how to rank the map? – user51324 Jun 09 '14 at 12:30
  • @user3590882 Glad it helped you. :) As far as ordering the `HashMap`, you really don't, usually. A `HashMap` is fundamentally unordered. If you want to sort based on the key, you can use a `TreeMap`, but if you want to sort of the value, as I suspect, it becomes a bit harder, especially since there can be identical values (whereas the key is unique). You can check out [this Q&A for more information](http://stackoverflow.com/a/8119401/1435657). – asteri Jun 09 '14 at 12:33
  • I did this map=new TreeMap(map); And I have the map sorted by String, but how to sort it by key value? I tried map=new TreeMap(map.values); but it's not recognized... PS: How to write a text like a code in this forum? – user51324 Jun 10 '14 at 15:05
0

You need to first create a Language class:

public class Language {
  private String name;
  private int count;

  public Language(String name) { this.name = name; this.count = 0; }
  public String getName() { return this.name; }
  public int getCount() { return this.count; }
  public void setCount(int count) { this.count = count; }
}

And then, create a list of languages from the ArrayList:

List<String> languageNames = // your language names
Map<String, Language> map = new HashMap<String, Language>();

for (String languageName : languageNames) {
  Language language = map.get(languageName);
  if (language == null) {
    language = new Language(languageName);
  } else {
    language.setCount(language.getCount() + 1);
  }
  map.put(languageName, language);
}

List<Language> languages = new ArrayList<Language>(map.values());

After that, we sort, and print the languages:

Collections<Language>.sort(languages, new Comparator<Language>() {
  public int compare(Language l1, Language l2) {
    return l1.getCount() - l2.getCount();
  }
});

System.out.println(languages);
fajarkoe
  • 1,543
  • 10
  • 12
  • How to use this on the code of Jeff Gohlke? Because his code works on my ArrayList and your code is not the same that I need, so I have to adapt your code to mine. But how? Should I take only the third part about Collection? – user51324 Jun 10 '14 at 09:25
  • OP wants to _Rank a List with int in Java_ which roughly translates into using a map. Don't you think that dedicating a whole class to this is a little too stiff? – VH-NZZ Jun 10 '14 at 23:50
  • We can avoid using classes. But, we need to somehow bind language name with its frequency (number of appearance). The Language class is used for this purpose. – fajarkoe Jun 11 '14 at 01:33