1. 引言
在日常开发中,经常会遇到这样一个需求:判断两个 List
是否相等——即它们是否包含相同的元素,并且元素顺序也完全一致。
List
是一种有序集合(ordered collection),这意味着元素的顺序是它语义的一部分。这一点非常关键,踩坑的同学往往是忽略了“顺序”这个前提。
我们先来看官方文档中对 List#equals
的定义:
两个列表当且仅当它们包含相同的元素且顺序相同时,才被认为是相等的。
✅ 这个定义保证了不同 List
实现类之间(比如 ArrayList
和 LinkedList
)也能正确地进行比较。
为了演示,我们定义以下三组测试数据:
List<String> list1 = Arrays.asList("1", "2", "3", "4");
List<String> list2 = Arrays.asList("1", "2", "3", "4");
List<String> list3 = Arrays.asList("1", "2", "4", "3");
list1
和list2
:内容相同,顺序相同 → 应该相等list1
和list3
:内容相同,但顺序不同 → 不相等
接下来我们看看在主流测试框架中如何写出正确的断言。
2. 使用 JUnit 断言
如果你用的是 JUnit(通常是 JUnit 4),可以直接使用 Assert.assertEquals
来比较两个 List。
@Test
public void whenTestingForEquality_ShouldBeEqual() throws Exception {
Assert.assertEquals(list1, list2); // ✅ 相等
Assert.assertNotSame(list1, list2); // ✅ 不是同一个对象引用
Assert.assertNotEquals(list1, list3); // ✅ 顺序不同,不相等
}
⚠️ 注意:
assertEquals
调用的是List
接口自身的equals
方法,已经考虑了顺序。assertNotSame
只是确认两个变量不是指向同一对象,避免误判引用相等为值相等。
简单粗暴,适合大多数单元测试场景。
3. 使用 TestNG 断言
TestNG 的用法和 JUnit 几乎一模一样,但注意导入的包不同:
import org.testng.Assert;
代码几乎可以完全复制:
@Test
public void whenTestingForEquality_ShouldBeEqual() throws Exception {
Assert.assertEquals(list1, list2); // ✅
Assert.assertNotSame(list1, list2); // ✅
Assert.assertNotEquals(list1, list3); // ✅
}
❌ 常见错误:把 JUnit 的 Assert
和 TestNG 的搞混,导致静态导入冲突或行为差异。记得检查 import!
4. 使用 AssertJ(推荐)
AssertJ 提供了更流畅、更具可读性的链式断言 API,强烈推荐在复杂逻辑或需要高表达力的测试中使用。
@Test
public void whenTestingForEquality_ShouldBeEqual() throws Exception {
assertThat(list1)
.isEqualTo(list2) // ✅ 完全相等
.isNotEqualTo(list3); // ✅ 不相等
// 也可以显式调用 equals 方法做布尔判断
assertThat(list1.equals(list2)).isTrue(); // ✅
assertThat(list1.equals(list3)).isFalse(); // ✅
}
✅ 优势:
- 可读性强,一眼看出断言意图
- 支持丰富的扩展断言(如
containsExactly
,hasSize()
等) - 错误信息更友好,调试省时间
如果你的项目还没引入 AssertJ,真的建议加上。长期来看能显著提升测试代码质量。
5. 总结
判断两个 List
是否相等,核心在于理解 List#equals
的设计语义:
✅ 元素相同 + 顺序一致 = 相等
我们展示了三种主流测试框架下的写法:
框架 | 特点 |
---|---|
JUnit | 基础必备,简单直接 |
TestNG | 注意包名别导错 |
AssertJ | ✅ 推荐,表达力强,易维护 |
所有示例代码均可在 GitHub 获取:
👉 https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-collections-list-2
📌 小贴士:如果不需要比较顺序,而是只关心“元素是否相同”,那应该用 Set
或手动排序后再比对。List
的顺序是它的灵魂,别轻易忽略。