@@ -398,8 +398,9 @@ pub struct HashMap<K, V, S = RandomState> {
398
398
}
399
399
400
400
/// Search for a pre-hashed key.
401
+ /// If you don't already know the hash, use search or search_mut instead
401
402
#[ inline]
402
- fn search_hashed < K , V , M , F > ( table : M , hash : SafeHash , mut is_match : F ) -> InternalEntry < K , V , M >
403
+ fn search_hashed < K , V , M , F > ( table : M , hash : SafeHash , is_match : F ) -> InternalEntry < K , V , M >
403
404
where M : Deref < Target = RawTable < K , V > > ,
404
405
F : FnMut ( & K ) -> bool
405
406
{
@@ -410,6 +411,18 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
410
411
return InternalEntry :: TableIsEmpty ;
411
412
}
412
413
414
+ search_hashed_nonempty ( table, hash, is_match)
415
+ }
416
+
417
+ /// Search for a pre-hashed key when the hash map is known to be non-empty.
418
+ #[ inline]
419
+ fn search_hashed_nonempty < K , V , M , F > ( table : M , hash : SafeHash , mut is_match : F )
420
+ -> InternalEntry < K , V , M >
421
+ where M : Deref < Target = RawTable < K , V > > ,
422
+ F : FnMut ( & K ) -> bool
423
+ {
424
+ // Do not check the capacity as an extra branch could slow the lookup.
425
+
413
426
let size = table. size ( ) ;
414
427
let mut probe = Bucket :: new ( table, hash) ;
415
428
let mut displacement = 0 ;
@@ -543,24 +556,36 @@ impl<K, V, S> HashMap<K, V, S>
543
556
}
544
557
545
558
/// Search for a key, yielding the index if it's found in the hashtable.
546
- /// If you already have the hash for the key lying around, use
547
- /// search_hashed.
559
+ /// If you already have the hash for the key lying around, or if you need an
560
+ /// InternalEntry, use search_hashed or search_hashed_nonempty .
548
561
#[ inline]
549
- fn search < ' a , Q : ?Sized > ( & ' a self , q : & Q ) -> InternalEntry < K , V , & ' a RawTable < K , V > >
562
+ fn search < ' a , Q : ?Sized > ( & ' a self , q : & Q )
563
+ -> Option < FullBucket < K , V , & ' a RawTable < K , V > > >
550
564
where K : Borrow < Q > ,
551
565
Q : Eq + Hash
552
566
{
567
+ if self . is_empty ( ) {
568
+ return None ;
569
+ }
570
+
553
571
let hash = self . make_hash ( q) ;
554
- search_hashed ( & self . table , hash, |k| q. eq ( k. borrow ( ) ) )
572
+ search_hashed_nonempty ( & self . table , hash, |k| q. eq ( k. borrow ( ) ) )
573
+ . into_occupied_bucket ( )
555
574
}
556
575
557
576
#[ inline]
558
- fn search_mut < ' a , Q : ?Sized > ( & ' a mut self , q : & Q ) -> InternalEntry < K , V , & ' a mut RawTable < K , V > >
577
+ fn search_mut < ' a , Q : ?Sized > ( & ' a mut self , q : & Q )
578
+ -> Option < FullBucket < K , V , & ' a mut RawTable < K , V > > >
559
579
where K : Borrow < Q > ,
560
580
Q : Eq + Hash
561
581
{
582
+ if self . is_empty ( ) {
583
+ return None ;
584
+ }
585
+
562
586
let hash = self . make_hash ( q) ;
563
- search_hashed ( & mut self . table , hash, |k| q. eq ( k. borrow ( ) ) )
587
+ search_hashed_nonempty ( & mut self . table , hash, |k| q. eq ( k. borrow ( ) ) )
588
+ . into_occupied_bucket ( )
564
589
}
565
590
566
591
// The caller should ensure that invariants by Robin Hood Hashing hold
@@ -1118,7 +1143,7 @@ impl<K, V, S> HashMap<K, V, S>
1118
1143
where K : Borrow < Q > ,
1119
1144
Q : Hash + Eq
1120
1145
{
1121
- self . search ( k) . into_occupied_bucket ( ) . map ( |bucket| bucket. into_refs ( ) . 1 )
1146
+ self . search ( k) . map ( |bucket| bucket. into_refs ( ) . 1 )
1122
1147
}
1123
1148
1124
1149
/// Returns true if the map contains a value for the specified key.
@@ -1145,7 +1170,7 @@ impl<K, V, S> HashMap<K, V, S>
1145
1170
where K : Borrow < Q > ,
1146
1171
Q : Hash + Eq
1147
1172
{
1148
- self . search ( k) . into_occupied_bucket ( ) . is_some ( )
1173
+ self . search ( k) . is_some ( )
1149
1174
}
1150
1175
1151
1176
/// Returns a mutable reference to the value corresponding to the key.
@@ -1174,7 +1199,7 @@ impl<K, V, S> HashMap<K, V, S>
1174
1199
where K : Borrow < Q > ,
1175
1200
Q : Hash + Eq
1176
1201
{
1177
- self . search_mut ( k) . into_occupied_bucket ( ) . map ( |bucket| bucket. into_mut_refs ( ) . 1 )
1202
+ self . search_mut ( k) . map ( |bucket| bucket. into_mut_refs ( ) . 1 )
1178
1203
}
1179
1204
1180
1205
/// Inserts a key-value pair into the map.
@@ -1234,11 +1259,7 @@ impl<K, V, S> HashMap<K, V, S>
1234
1259
where K : Borrow < Q > ,
1235
1260
Q : Hash + Eq
1236
1261
{
1237
- if self . table . size ( ) == 0 {
1238
- return None ;
1239
- }
1240
-
1241
- self . search_mut ( k) . into_occupied_bucket ( ) . map ( |bucket| pop_internal ( bucket) . 1 )
1262
+ self . search_mut ( k) . map ( |bucket| pop_internal ( bucket) . 1 )
1242
1263
}
1243
1264
1244
1265
/// Removes a key from the map, returning the stored key and value if the
@@ -1269,12 +1290,7 @@ impl<K, V, S> HashMap<K, V, S>
1269
1290
where K : Borrow < Q > ,
1270
1291
Q : Hash + Eq
1271
1292
{
1272
- if self . table . size ( ) == 0 {
1273
- return None ;
1274
- }
1275
-
1276
1293
self . search_mut ( k)
1277
- . into_occupied_bucket ( )
1278
1294
. map ( |bucket| {
1279
1295
let ( k, v, _) = pop_internal ( bucket) ;
1280
1296
( k, v)
@@ -2632,15 +2648,11 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
2632
2648
2633
2649
#[ inline]
2634
2650
fn get ( & self , key : & Q ) -> Option < & K > {
2635
- self . search ( key) . into_occupied_bucket ( ) . map ( |bucket| bucket. into_refs ( ) . 0 )
2651
+ self . search ( key) . map ( |bucket| bucket. into_refs ( ) . 0 )
2636
2652
}
2637
2653
2638
2654
fn take ( & mut self , key : & Q ) -> Option < K > {
2639
- if self . table . size ( ) == 0 {
2640
- return None ;
2641
- }
2642
-
2643
- self . search_mut ( key) . into_occupied_bucket ( ) . map ( |bucket| pop_internal ( bucket) . 0 )
2655
+ self . search_mut ( key) . map ( |bucket| pop_internal ( bucket) . 0 )
2644
2656
}
2645
2657
2646
2658
#[ inline]
0 commit comments