在Java开发中,统计集合内元素出现次数是非常常见的需求,比如统计订单列表中每个商品的出现次数、统计日志集合中不同错误类型的出现频率等,下面介绍几种常用的实现方式。

使用HashMap手动统计
这种方式是最基础也兼容性最好的实现方案,核心思路是遍历集合元素,以元素作为键,出现次数作为值存储在HashMap中,每次遇到相同元素就将对应的值加1。
以下是统计字符串列表元素出现次数的示例代码:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CountDemo {
public static void main(String[] args) {
// 初始化待统计的集合
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("apple");
list.add("orange");
list.add("banana");
list.add("apple");
// 创建HashMap存储统计结果
Map<String, Integer> countMap = new HashMap<>();
// 遍历集合元素
for (String item : list) {
// 如果元素已存在,次数加1,否则初始化为1
countMap.put(item, countMap.getOrDefault(item, 0) + 1);
}
// 输出统计结果
for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
System.out.println(entry.getKey() + " 出现次数: " + entry.getValue());
}
}
}
这种方式的优点是兼容性好,支持所有Java版本,同时可以自定义统计逻辑,比如可以过滤掉不需要统计的元素。缺点是需要手动编写遍历和计数逻辑,代码量相对较多。
使用Java 8 Stream API统计
Java 8引入了Stream API,提供了更简洁的集合操作方式,可以使用groupingBy和counting方法快速实现元素计数统计。
示例代码如下:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamCountDemo {
public static void main(String[] args) {
// 初始化待统计的集合
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("apple");
list.add("orange");
list.add("banana");
list.add("apple");
// 使用Stream API统计元素次数
Map<String, Long> countMap = list.stream()
.collect(Collectors.groupingBy(item -> item, Collectors.counting()));
// 输出统计结果
countMap.forEach((key, value) -> System.out.println(key + " 出现次数: " + value));
}
}
这种方式的优点是代码非常简洁,一行核心代码就能完成统计,可读性强。缺点是仅支持Java 8及以上版本,如果需要兼容更低版本则无法使用。
使用Collections.frequency方法统计单个元素
如果只需要统计集合中某一个特定元素的出现次数,可以使用Collections工具类的frequency方法,该方法接收集合和目标元素作为参数,返回目标元素在集合中出现的次数。
示例代码如下:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class FrequencyDemo {
public static void main(String[] args) {
// 初始化待统计的集合
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("apple");
list.add("orange");
list.add("banana");
list.add("apple");
// 统计apple出现的次数
int appleCount = Collections.frequency(list, "apple");
System.out.println("apple 出现次数: " + appleCount);
// 统计banana出现的次数
int bananaCount = Collections.frequency(list, "banana");
System.out.println("banana 出现次数: " + bananaCount);
}
}
这种方式适合只需要统计少数几个特定元素的场景,使用起来非常方便,但如果需要统计所有元素的次数,需要多次调用该方法,效率不如前两种方式。
自定义对象集合的元素统计
当集合中的元素是自定义对象时,通常需要根据对象的某个属性来统计次数,比如统计用户列表中每个年龄段的用户数量,这时候可以根据需求调整统计的键。
示例代码如下,假设我们有一个User类,需要统计相同年龄的用户数量:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
}
public class CustomObjectCountDemo {
public static void main(String[] args) {
// 初始化自定义对象集合
List<User> userList = new ArrayList<>();
userList.add(new User("张三", 20));
userList.add(new User("李四", 22));
userList.add(new User("王五", 20));
userList.add(new User("赵六", 22));
userList.add(new User("钱七", 20));
// 按年龄统计用户数量
Map<Integer, Integer> ageCountMap = new HashMap<>();
for (User user : userList) {
int age = user.getAge();
ageCountMap.put(age, ageCountMap.getOrDefault(age, 0) + 1);
}
// 输出统计结果
for (Map.Entry<Integer, Integer> entry : ageCountMap.entrySet()) {
System.out.println("年龄 " + entry.getKey() + " 的用户数量: " + entry.getValue());
}
}
}
如果是Java 8及以上版本,同样可以使用Stream API实现自定义对象集合的统计,核心是指定分组的键为对象的对应属性即可。
不同方案的适用场景总结
- 如果需要兼容Java 8以下的版本,或者需要自定义复杂的统计逻辑,优先选择HashMap手动统计的方式
- 如果项目已经使用Java 8及以上版本,且统计逻辑比较简单,优先选择Stream API的方式,代码更简洁
- 如果只需要统计少数几个特定元素的出现次数,使用Collections.frequency方法更方便
- 如果集合元素是自定义对象,需要根据对象属性统计,可以在上述方案的基础上调整分组的键即可