5

I'd like to count up List's size by element. For example,

List<String> source = Arrays.asList("USA", "USA", "Japan", "China", "China", "USA", "USA");

I'd like to create object (Map) from this source, such as,

int usa_count = result.get("USA").intValue(); // == 4
int javan_count = result.get("Japan").intValue(); // == 1
int china_count = result.get("China").intValue(); // == 2
int uk_count = result.get("UK").intValue(); // == 0 or NPE (both OK)

Now, I composed below.

Map<String, Integer> result = new HashMap<>();
for (String str : source) {
    Integer i = result.getOrDefault(str, Integer.valueOf(0));
    result.put(str, i + 1);
}

Though, this is enough to my purpose, I think this is not elegant code, and I wanna be a elegant coder. I use Java8. Is there any elegant solution instead of my solution?

xenteros
  • 15,586
  • 12
  • 56
  • 91

4 Answers4

3

You can use frequency method in collection.

int usa_count = Collections.frequency(source, "USA");
int javan_count = Collections.frequency(source, "Japan");
int china_count = Collections.frequency(source, "CHINA"); 
int uk_count = Collections.frequency(source, "UK");

Refer:https://www.tutorialspoint.com/java/util/collections_frequency.htm

in Java 8:-

groupingBy collector allows to group together elements that have the same classification into a map.

Map<String, Long> countContries = source.stream().collect(Collectors.groupingBy(Function.identity() , Collectors.counting()));

Refer: https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html

https://www.mkyong.com/java8/java-8-collectors-groupingby-and-mapping-example/

Chandana Kumara
  • 2,485
  • 1
  • 22
  • 25
3

You can use streams groupingBy as shown below:

List<String> source = Arrays.asList("USA", "USA", "Japan", 
        "China", "China", "USA", "USA");

Map<String, Long> result =
                source.stream().collect(
                        //Use groupingBy
                        Collectors.groupingBy(
                                Function.identity(), Collectors.counting()
                        )
                );


System.out.println(result);

Output: {USA=4, China=2, Japan=1}

Vasu
  • 21,832
  • 11
  • 51
  • 67
1

You can use the Stream-api to do this.

source.stream()
      .collect(Collectors.groupingBy(
                      Function.identity(), 
                      Collectors.counting());

The groupingBy-collector generates a map where the keys are given by the first parameter. The second parameter can be omitted to give a list of each group that has the same key. In your case, that would give this:

Map("USA" -> List("USA", "USA", "USA", "USA"),
    "Japan" -> List("Japan"),
    "Chine" -> List("China", China"))

By giving a collector as a parameter, it will collect each group (in this case, counting the number of elements).

marstran
  • 26,413
  • 5
  • 61
  • 67
0

IMHO your code is OK, but it could be simplified slightly:

Map<String, Integer> result = new HashMap<>();
for (String str : source) {
    int i = result.getOrDefault(str, 0);
    result.put(str, i + 1);
}

or even:

Map<String, Integer> result = new HashMap<>();
for (String str : source) {
    result.put(str, result.getOrDefault(str, 0) + 1);
}
Maurice Perry
  • 9,261
  • 2
  • 12
  • 24