hashset结合泛型实现类型安全去重,依赖编译期类型检查与运行期hashcode/equals协同:泛型确保add等操作类型合规、遍历免强转,而正确重写hashcode/equals才是去重生效前提。

泛型声明确保编译期类型约束
声明 HashSet 时指定泛型参数,如 Set<string></string> 或 Set<student></student>,编译器会强制所有 add、iterator、stream 等操作只接受对应类型或其子类:
-
Set<integer> set = new HashSet();</integer>→ 只能 add Integer 或 int(自动装箱) - 若写
set.add("abc"),编译直接报错,不会等到运行时才发现类型错误 - 遍历时无需手动强转:
for (Integer i : set),变量 i 直接是 Integer 类型
泛型与去重逻辑的配合要点
泛型不改变去重行为,但为正确去重提供前提条件:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 基本类型包装类(String、Integer、LocalDate 等)已重写 hashCode/equals,开箱即用
- 自定义类必须重写这两个方法,且重写逻辑需覆盖泛型声明中参与比较的字段
- 泛型类型参数应与 equals 判定逻辑一致——例如用
Set<student></student>,但 equals 只比 name,那 age 不同的同名学生仍会被视为重复
常见泛型使用场景示例
以下写法兼顾类型安全与去重效果:
-
数组去重:
int[] arr = {1,2,2,3}; Set<integer> set = new HashSet(Arrays.stream(arr).boxed().toList());</integer> -
List 去重并保持泛型一致性:
List<string> list = Arrays.asList("a","b","a"); Set<string> unique = new HashSet(list);</string></string> -
自定义对象(带泛型声明):
Set<student> students = new HashSet(); students.add(new Student("Tom", 20));</student>——前提是 Student 正确重写了 hashCode 和 equals
注意泛型擦除带来的实际限制
运行时泛型信息不存在,所以不能依赖泛型做 instanceof 判断或创建泛型数组,但去重不受影响:
- 无法写
new HashSet<string>() {{ add("x"); }}.getClass() == HashSet.class</string>来区分类型,但不影响功能 - 反序列化时需显式传入 TypeReference 或 Class 对象,否则泛型信息丢失可能导致类型不安全
- 泛型不解决“逻辑重复”问题——比如两个 Student 对象字段相同但未重写 equals,泛型再严格也无法让它们去重
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










