0

0

Collections.frequency方法的应用

P粉602998670

P粉602998670

发布时间:2025-09-21 22:43:01

|

207人浏览过

|

来源于php中文网

原创

Collections.frequency用于统计集合中指定元素的出现次数,基于equals方法比较,适用于快速、简洁地统计单个元素频次,尤其在代码可读性和维护性上优势明显。

collections.frequency方法的应用

Collections.frequency
方法的核心作用,就是快速统计一个集合(
Collection
)中某个特定元素出现的次数。它提供了一种简洁、内置的方式来完成这项常见的计数任务,省去了我们手动遍历集合并维护计数器的麻烦。

说起

Collections.frequency
,它在Java标准库里算是个小巧但挺实用的工具。我记得刚开始写Java那会儿,要是想知道一个列表里某个字符串出现了多少次,最直观的做法就是写个
for
循环,然后里面一个
if
判断,匹配上了就
count++
。后来接触到
Collections
工具类,发现它竟然直接提供了
frequency
方法,当时就觉得“哦,原来还有这种更优雅的写法啊”。

它的用法其实很简单:

int count = Collections.frequency(collection, object);
第一个参数是你想要统计的那个
Collection
,比如
ArrayList
LinkedList
或者
HashSet
(尽管在
HashSet
里统计频率通常没啥意义,因为元素不重复,但语法上是允许的)。第二个参数就是你想要统计出现次数的那个
object

举个例子吧,假设你有一个字符串列表,想知道“apple”出现了几次:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class FrequencyExample {
    public static void main(String[] args) {
        List fruits = new ArrayList<>();
        fruits.add("apple");
        fruits.add("banana");
        fruits.add("apple");
        fruits.add("orange");
        fruits.add("apple");

        int appleCount = Collections.frequency(fruits, "apple");
        System.out.println("Apple appears: " + appleCount + " times."); // 输出 3
    }
}

是不是比手写循环要清爽很多?这个方法内部其实也是遍历,但它把这些细节封装起来了,让我们的代码更专注于业务逻辑,而不是重复性的计数实现。而且,它在比较元素时用的是

equals()
方法,这很重要。这意味着如果你自定义了对象,并重写了
equals()
,它会按照你的逻辑去判断“相等”。如果没重写,那默认就是比较对象的内存地址了,这在大多数场景下可能不是你想要的。

Collections.frequency与手动循环计数:性能与场景考量

我们常常会纠结,到底是直接用

Collections.frequency
好,还是自己写个
for
循环来计数更好?这其实不是一个非黑即白的问题,它涉及到性能、代码可读性以及具体的应用场景。

从性能上看,

Collections.frequency
的底层实现,对于
List
这类有序集合,它就是简单地遍历整个集合,时间复杂度是O(n),其中n是集合的大小。这和你自己写一个
for
循环去遍历计数,在渐进时间复杂度上是完全一致的。所以,对于单个元素的频率统计,性能差异微乎其微,甚至可以说忽略不计。但如果你需要统计集合中 所有不同元素 的频率,那么
Collections.frequency
就不是最佳选择了。因为它每次调用都是完整遍历一次,如果你有m个不同的元素要统计,那总复杂度就是O(m*n),这显然效率不高。

在这种需要统计所有元素频率的场景下,一个更高效的做法是使用

HashMap
或者Java 8的
Stream
API配合
Collectors.groupingBy
Collectors.counting
。例如:

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class StreamFrequencyExample {
    public static void main(String[] args) {
        List fruits = Arrays.asList("apple", "banana", "apple", "orange", "apple");
        Map frequencyMap = fruits.stream()
                                             .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        System.out.println(frequencyMap); // {banana=1, orange=1, apple=3}
    }
}

这个方法的复杂度是O(n),因为它只遍历了一次集合。

所以,我的个人观点是:

  • 当只需要统计集合中 一个或少数几个特定元素 的出现次数时,
    Collections.frequency
    是首选。
    它代码简洁,意图明确,可读性极佳。
  • 当需要统计集合中 所有不同元素 的出现次数,或者需要更复杂的聚合操作时,考虑使用
    HashMap
    手动构建频率映射,或者利用
    Stream
    API。
    这样能获得更好的整体性能。
  • 对于非常大的集合,如果性能是极致的瓶颈,并且你只需要判断某个元素是否存在,而不是精确计数,
    HashSet
    contains
    方法会更快(O(1)平均)。
    但这和计数不是一个目的。

处理Null值和自定义对象:Collections.frequency的边界与注意事项

在使用

Collections.frequency
时,有几个点是需要特别留意的,尤其是涉及到
null
值和自定义对象时。

NightCafe
NightCafe

一款 AI 艺术生成器应用程序,具有多种 AI 艺术生成方法。

下载

首先是

null
值。是的,
Collections.frequency
是可以用来统计
null
在集合中出现的次数的。只要你的集合允许存储
null
(比如
ArrayList
),并且你传入的
object
参数就是
null
,它就能正常工作:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class NullFrequencyExample {
    public static void main(String[] args) {
        List items = new ArrayList<>();
        items.add("item1");
        items.add(null);
        items.add("item2");
        items.add(null);

        int nullCount = Collections.frequency(items, null);
        System.out.println("Null appears: " + nullCount + " times."); // 输出 2
    }
}

这在某些数据清洗或校验的场景下,可能会派上用场,比如你想知道有多少条记录是缺失了某个字段的。

然后是自定义对象。前面提到过,

Collections.frequency
在比较元素时,依赖的是元素的
equals()
方法。如果你有一个自定义的类,比如
Person

class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 省略getter/setter,为了简洁,这里不写,但实际项目中应该有
    // 注意:这里没有重写equals()和hashCode()
}

如果你不重写

equals()
hashCode()
方法,那么默认的
equals()
方法会比较两个对象的内存地址。这意味着,即使两个
Person
对象的
name
age
都一样,但如果它们是不同的实例,
Collections.frequency
也会认为它们是不同的。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CustomObjectFrequencyExample {
    public static void main(String[] args) {
        List people = new ArrayList<>();
        people.add(new Person("Alice", 30));
        people.add(new Person("Bob", 25));
        people.add(new Person("Alice", 30)); // 逻辑上和第一个Alice相同,但内存地址不同

        int aliceCount = Collections.frequency(people, new Person("Alice", 30));
        // 这里输出 0 是大概率事件,因为 new Person("Alice", 30) 又创建了一个新的对象实例,
        // 它的内存地址肯定和集合里的实例不同。
        System.out.println("Alice appears (without equals/hashCode): " + aliceCount + " times.");
    }
}

这里输出

0
是大概率事件,因为
new Person("Alice", 30)
又创建了一个新的对象实例,它的内存地址肯定和集合里的实例不同。

为了让

Collections.frequency
能够正确地识别“相同”的自定义对象,你必须重写
equals()
hashCode()
方法
。这是一个Java编程的基本约定,尤其是在将对象放入集合(特别是
HashMap
HashSet
)时。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects; // 导入Objects工具类,方便生成equals和hashCode

class PersonWithEqualsHashCode {
    String name;
    int age;

    public PersonWithEqualsHashCode(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PersonWithEqualsHashCode person = (PersonWithEqualsHashCode) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
    // 省略getter/setter
}

public class CustomObjectFrequencyWithEqualsHashCodeExample {
    public static void main(String[] args) {
        List people = new ArrayList<>();
        people.add(new PersonWithEqualsHashCode("Alice", 30));
        people.add(new PersonWithEqualsHashCode("Bob", 25));
        people.add(new PersonWithEqualsHashCode("Alice", 30)); // 逻辑上和第一个Alice相同

        int aliceCount = Collections.frequency(people, new PersonWithEqualsHashCode("Alice", 30));
        System.out.println("Alice appears (with equals/hashCode): " + aliceCount + " times."); // 输出 2
    }
}

现在,

Collections.frequency
就能正确地识别出两个逻辑上相同的“Alice”了。这不仅仅是
frequency
方法的问题,而是所有依赖对象相等性判断的Java集合操作的共同点。

Collections.frequency在实际项目中的高级应用案例

虽然

Collections.frequency
看起来简单,但在某些实际场景下,它能提供非常简洁有效的解决方案。我来分享几个我个人觉得比较有意思的应用场景。

1. 快速判断元素是否出现特定次数: 有时候我们不只是想知道出现多少次,而是想知道它是否“恰好”出现了X次,或者“至少”出现了X次。比如,在一个投票系统中,你想知道某个选项是否获得了至少10票:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class VoteCountExample {
    public static void main(String[] args) {
        List votes = Arrays.asList("optionA", "optionB", "optionA", "optionC", "optionA",
                                           "optionA", "optionB", "optionA", "optionC", "optionA",
                                           "optionA", "optionB", "optionA"); // optionA 出现了 9 次
        int requiredVotes = 10;
        if (Collections.frequency(votes, "optionA") >= requiredVotes) {
            System.out.println("Option A has enough votes to pass.");
        } else {
            System.out.println("Option A needs more votes. Currently: " + Collections.frequency(votes, "optionA"));
        }
    }
}

这种场景下,

frequency
的直观性就体现出来了。

2. 集合的简单差异分析(非精确): 这可能有点“歪用”,但偶尔我会用它来做一些非常粗略的集合内容对比。比如,你有两个列表

listA
listB
,你想快速知道
listA
中某个元素
X
出现的次数,和
listB
X
出现的次数是否一致。如果数量不一致,那这两个列表在某种程度上肯定有差异。

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class ListDifferenceExample {
    public static void main(String[] args) {
        List listA = Arrays.asList("apple", "banana", "apple");
        List listB = Arrays.asList("apple", "orange", "apple");

        String target = "apple";
        if (Collections.frequency(listA, target) != Collections.frequency(listB, target)) {

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

236

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

458

2024.03.01

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

778

2023.08.22

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

198

2023.11.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1501

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

624

2023.11.24

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 9.9万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.2万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号