如何为我自己的结构实现 Eq 和 Hash 以将它们用作 HashMap 键?
How to implement Eq and Hash for my own structs to use them as a HashMap key?
我有两个结构,A
和 B
,我想使用 HashMap<A, B>
。我有一段这样的代码:
use std::collections::HashMap;
pub struct A {
x: i32,
y: i32,
title: String,
}
pub struct B {
a: u32,
b: u32,
}
fn main() {
let map = HashMap::new();
map.insert(
A {
x: 10,
y: 20,
title: "test".to_string(),
},
B { a: 1, b: 2 },
);
}
但是编译器给我这些错误:
error[E0277]: the trait bound `A: std::cmp::Eq` is not satisfied
--> src/main.rs:16:9
|
16 | map.insert(
| ^^^^^^ the trait `std::cmp::Eq` is not implemented for `A`
error[E0277]: the trait bound `A: std::hash::Hash` is not satisfied
--> src/main.rs:16:9
|
16 | map.insert(
| ^^^^^^ the trait `std::hash::Hash` is not implemented for `A`
我知道我必须实现这些特征,但是在网上搜索了几个小时后,我没有找到任何关于实现它们的信息。
我的实际代码比较复杂,我的结构包含其他结构(我已经编辑了代码)。
我已经实现了 Hash
特征:
impl std::hash::Hash for A {
fn hash<H>(&self, state: &mut H)
where
H: std::hash::Hasher,
{
state.write_i32(self.x);
state.finish();
}
}
我还为 PartialEq
做了一个实现:
impl PartialEq for A {
fn eq(&self, other: &A) -> bool {
self.x == other.x
}
}
但是编译器继续报错,这次是关于 Eq
:
error[E0277]: the trait bound `A: std::cmp::Eq` is not satisfied
--> src/main.rs:16:9
|
16 | map.insert(
| ^^^^^^ the trait `std::cmp::Eq` is not implemented for `A`
如何实施 Eq
?为什么文档中没有实现?
您可以让编译器为您派生这些实例,方法是在结构声明之前插入以下内容:
#[derive(PartialEq, Eq, Hash)]
pub struct A {
// ...
}
上的文档
Eq
就是我们所说的marker trait:它本身没有方法,它只是程序员表达struct验证某个属性的一种方式。你可以这样实现它:
impl Eq for Application {}
或者,在 Application
声明之上使用 #[derive(Eq)]
Eq
是受 PartialEq
约束的特征。这意味着您只能在也实现 PartialEq
的结构上实现它(这里就是这种情况)。通过实施 Eq
,您承诺 PartialEq
的实施是自反的(请参阅文档了解其含义)。
这就是 Rust 文档所说的如何编写自己的 Hash
实现:
use std::hash::{Hash, Hasher};
struct Person {
id: u32,
name: String,
phone: u64,
}
impl Hash for Person {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
self.phone.hash(state);
}
}
我有两个结构,A
和 B
,我想使用 HashMap<A, B>
。我有一段这样的代码:
use std::collections::HashMap;
pub struct A {
x: i32,
y: i32,
title: String,
}
pub struct B {
a: u32,
b: u32,
}
fn main() {
let map = HashMap::new();
map.insert(
A {
x: 10,
y: 20,
title: "test".to_string(),
},
B { a: 1, b: 2 },
);
}
但是编译器给我这些错误:
error[E0277]: the trait bound `A: std::cmp::Eq` is not satisfied
--> src/main.rs:16:9
|
16 | map.insert(
| ^^^^^^ the trait `std::cmp::Eq` is not implemented for `A`
error[E0277]: the trait bound `A: std::hash::Hash` is not satisfied
--> src/main.rs:16:9
|
16 | map.insert(
| ^^^^^^ the trait `std::hash::Hash` is not implemented for `A`
我知道我必须实现这些特征,但是在网上搜索了几个小时后,我没有找到任何关于实现它们的信息。
我的实际代码比较复杂,我的结构包含其他结构(我已经编辑了代码)。
我已经实现了 Hash
特征:
impl std::hash::Hash for A {
fn hash<H>(&self, state: &mut H)
where
H: std::hash::Hasher,
{
state.write_i32(self.x);
state.finish();
}
}
我还为 PartialEq
做了一个实现:
impl PartialEq for A {
fn eq(&self, other: &A) -> bool {
self.x == other.x
}
}
但是编译器继续报错,这次是关于 Eq
:
error[E0277]: the trait bound `A: std::cmp::Eq` is not satisfied
--> src/main.rs:16:9
|
16 | map.insert(
| ^^^^^^ the trait `std::cmp::Eq` is not implemented for `A`
如何实施 Eq
?为什么文档中没有实现?
您可以让编译器为您派生这些实例,方法是在结构声明之前插入以下内容:
#[derive(PartialEq, Eq, Hash)]
pub struct A {
// ...
}
上的文档
Eq
就是我们所说的marker trait:它本身没有方法,它只是程序员表达struct验证某个属性的一种方式。你可以这样实现它:
impl Eq for Application {}
或者,在 Application
声明之上使用 #[derive(Eq)]
Eq
是受 PartialEq
约束的特征。这意味着您只能在也实现 PartialEq
的结构上实现它(这里就是这种情况)。通过实施 Eq
,您承诺 PartialEq
的实施是自反的(请参阅文档了解其含义)。
这就是 Rust 文档所说的如何编写自己的 Hash
实现:
use std::hash::{Hash, Hasher};
struct Person {
id: u32,
name: String,
phone: u64,
}
impl Hash for Person {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
self.phone.hash(state);
}
}