Вы можете следовать идеям, описанным в . Как реализовать HashMap с двумя ключами? . Вот ответ «заимствованный объект-объект», ответ на ваш случай:
Создайте признак, который мы можем использовать в качестве общей цели Borrow
:
trait Key {
fn to_key(&self) -> (i32, &str);
}
Реализовать HashMap
-приобретенные черты для объекта-объекта:
use std::hash::{Hash, Hasher};
impl<'a> Hash for Key + 'a {
fn hash(&self, state: &mut H) {
self.to_key().hash(state)
}
}
impl<'a> PartialEq for Key + 'a {
fn eq(&self, other: &Self) -> bool {
self.to_key() == other.to_key()
}
}
impl<'a> Eq for Key + 'a {}
Реализовать признак для нашего основного типа и любых типов вторичного поиска:
impl Key for Complex {
fn to_key(&self) -> (i32, &str) {
(self.n, &self.s)
}
}
impl<'a> Key for (i32, &'a str) {
fn to_key(&self) -> (i32, &str) {
(self.0, self.1)
}
}
Реализовать Borrow
для всех типов поиска, возвращающих наш объект-объект:
use std::borrow::Borrow;
impl<'a> Borrow for Complex {
fn borrow(&self) -> &(Key + 'a) {
self
}
}
impl<'a> Borrow for (i32, &'a str) {
fn borrow(&self) -> &(Key + 'a) {
self
}
}
Преобразовать объект-объект во время запроса:
assert_eq!(Some(&123), m.get((42, "foo").borrow() as &Key));
Важным «полученным» является то, что весь ваш первичный ключ и ваши вторичные ключи должны иметь хэш таким же образом. Это означает, что одни и те же значения должны идти в вычисление хэша в том же порядке и количестве.
Вы можете определить Hash
вручную, чтобы убедиться, что ваш основной и дополнительный ключи hash одинаковы!
Вот еще один пример, на этот раз с перечислением:
#[derive(Debug, PartialEq, Eq)]
enum ConfigKey {
Text(String),
Binary(Vec),
}
Мы создаем параллельное перечисление, состоящее только из ссылок, поэтому его легко создать. Важно, чтобы мы определяли одни и те же варианты и в том же порядке, что и первичное перечисление, чтобы они были хэшированы одинаково. Мы полагаемся на то, что хеш String
и &str
использует тот же алгоритм, что и Vec
и &[T]
:
impl ConfigKey {
fn as_ref(&self) -> ConfigKeyRef {
match self {
ConfigKey::Text(t) => ConfigKeyRef::Text(t),
ConfigKey::Binary(b) => ConfigKeyRef::Binary(b),
}
}
}
#[derive(Hash, PartialEq, Eq)]
enum ConfigKeyRef<'a> {
Text(&'a str),
Binary(&'a [u8]),
}
Мы используем это новое перечисление как наш общий базовый тип ключа :
trait Key {
fn to_key(&self) -> ConfigKeyRef;
}
И реализуем нашу черту для наших первичных и вторичных ключей:
impl Key for ConfigKey {
fn to_key(&self) -> ConfigKeyRef {
self.as_ref()
}
}
impl<'a> Key for &'a str {
fn to_key(&self) -> ConfigKeyRef {
ConfigKeyRef::Text(self)
}
}
Вам не нужно создавать Timestamp
s. Вы можете сделать это с помощью Calendar
.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
calendar.set(Calendar.MINUTE, minute);
if(calendar.before(Calendar.getInstance())) {
calendar.add(Calendar.DATE, 1);
}
alarmManager.set(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), pendingDinnerIntent);
Я бы также упомянул, что с KitKat, если ваш targetSdkVersion
равен 19 или выше, метод AlarmManager#set()
не является точным. Если вы хотите, чтобы ваш будильник срабатывал в определенное время, вам нужно использовать метод setExact*()
.