实现了一个struct,然后new出两个实例,比较它们是否相等,会报错,形如:
struct Man{
pub age: i32,
pub name: String,
}
fn test_1(){
let x1 = Man{
age: 11,
name: String::from("tim"),
};
let x2 = Man{
age: 12,
name: String::from("sam"),
};
assert_eq!(x1, x2);
}
fn main() {
test_1();
}
/*
运行结果:
error[E0369]: binary operation `==` cannot be applied to type `Man`
--> src/main.rs:18:5
|
18 | assert_eq!(x1, x2);
| ^^^^^^^^^^^^^^^^^^^
| |
| Man
| Man
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `Man`
*/
这个报错,是没有实现PartialEq特质。
这个特质相关的文档在这里 https://doc.rust-lang.org/std/cmp/index.html
PartialEq文档在这里 https://doc.rust-lang.org/std/cmp/trait.PartialEq.html ,实现它即可,不报错了:
#[derive(Debug)]
struct Man{
pub age: i32,
pub name: String,
}
impl PartialEq for Man{
fn eq(&self, other: &Self) -> bool {
(self.age == other.age) && (self.name == other.name)
}
}
fn test_1(){
let x1 = Man{
age: 11,
name: String::from("tim"),
};
let x2 = Man{
age: 12,
name: String::from("sam"),
};
assert_eq!(x1, x2);
}
fn main() {
test_1();
}
如果将实例加入到HashMap会报错,提示没有实现Eq和Hash特质:
use std::collections::HashMap;
#[derive(Debug)]
struct Man{
pub age: i32,
pub name: String,
}
impl PartialEq for Man{
fn eq(&self, other: &Self) -> bool {
(self.age == other.age) && (self.name == other.name)
}
}
fn test_1(){
let x1 = Man{
age: 11,
name: String::from("tim"),
};
let x2 = Man{
age: 12,
name: String::from("sam"),
};
let mut ahash = HashMap::new();
ahash.insert(&x1, 1i32);
assert_eq!(x1, x2);
}
fn main() {
test_1();
}
/*
运行结果:
error[E0277]: the trait bound `Man: std::cmp::Eq` is not satisfied
--> src/main.rs:27:11
|
27 | ahash.insert(&x1, 1i32);
| ^^^^^^ the trait `std::cmp::Eq` is not implemented for `Man`
|
= note: required because of the requirements on the impl of `std::cmp::Eq` for `&Man`
error[E0277]: the trait bound `Man: std::hash::Hash` is not satisfied
--> src/main.rs:27:11
|
27 | ahash.insert(&x1, 1i32);
| ^^^^^^ the trait `std::hash::Hash` is not implemented for `Man`
|
= note: required because of the requirements on the impl of `std::hash::Hash` for `&Man`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
*/
根据Eq的文档 https://doc.rust-lang.org/std/cmp/trait.Eq.html 可知,Eq是一个空的特质,没有具体方法,只是为编译器提供一个信息:这个对象会用到Eq操作。
HashMap,肯定需要Key实现了Hash。Hash特质的文档在https://doc.rust-lang.org/std/hash/trait.Hash.html 。如果struct的每个成员所属struct已经实现了Hash特质,只要#[derive(Hash)]即可,否认需要手动实现Hash,这里选择前者。
use std::collections::HashMap;
#[derive(Debug, Hash)]
struct Man{
pub age: i32,
pub name: String,
}
impl PartialEq for Man{
fn eq(&self, other: &Self) -> bool {
(self.age == other.age) && (self.name == other.name)
}
}
impl Eq for Man{}
fn test_1(){
let x1 = Man{
age: 11,
name: String::from("tim"),
};
let x2 = Man{
age: 12,
name: String::from("sam"),
};
let x3 = Man{
age: 11,
name: String::from("tim"),
};
let mut ahash = HashMap::new();
ahash.insert(&x1, 1i32);
assert_eq!(x1, x3);
assert_eq!(x1, x2);
}
fn main() {
test_1();
}
前面说过Eq特质是没有方法的,空的。通常的用法是,同时实现Eq和Hash特质,如果两个实例的Hash值相等,那么它们也就是相等的。通过Hash特质实现Eq特质。
那么,Eq和PartialEq有啥区别?Eq,从意义上而言,表示两个实例完全相等,这比较复杂,比如深度嵌套struct不好解决,干脆空掉。PartialEq的字面意思是部分相等,也就是两个实例内部的若干成员相等即可,当然,实际实现可以随意操作,全部成员相等也没问题。
那么,把kv值添加到HashMap的时候,相同hash的key是同一个key,会有更替关系。