@@ -1239,31 +1239,14 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
1239
1239
/// Return the value corresponding to the key in the map, or insert
1240
1240
/// and return the value if it doesn't exist.
1241
1241
pub fn find_or_insert < ' a > ( & ' a mut self , k : K , v : V ) -> & ' a mut V {
1242
- let hash = self . make_hash ( & k) ;
1243
- match self . search_hashed ( & hash, & k) {
1244
- Some ( idx) => {
1245
- let ( _, v_ref) = self . table . read_mut ( & idx) ;
1246
- v_ref
1247
- } ,
1248
- None => self . insert_hashed ( hash, k, v)
1249
- }
1242
+ self . find_with_or_insert_with ( k, v, |_k, _v, _a| ( ) , |_k, a| a)
1250
1243
}
1251
1244
1252
1245
/// Return the value corresponding to the key in the map, or create,
1253
1246
/// insert, and return a new value if it doesn't exist.
1254
1247
pub fn find_or_insert_with < ' a > ( & ' a mut self , k : K , f: |& K | -> V )
1255
1248
-> & ' a mut V {
1256
- let hash = self . make_hash ( & k) ;
1257
- match self . search_hashed ( & hash, & k) {
1258
- Some ( idx) => {
1259
- let ( _, v_ref) = self . table . read_mut ( & idx) ;
1260
- v_ref
1261
- } ,
1262
- None => {
1263
- let v = f ( & k) ;
1264
- self . insert_hashed ( hash, k, v)
1265
- }
1266
- }
1249
+ self . find_with_or_insert_with ( k, ( ) , |_k, _v, _a| ( ) , |k, _a| f ( k) )
1267
1250
}
1268
1251
1269
1252
/// Insert a key-value pair into the map if the key is not already present.
@@ -1275,12 +1258,66 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
1275
1258
v : V ,
1276
1259
f : |& K , & mut V |)
1277
1260
-> & ' a mut V {
1261
+ self . find_with_or_insert_with ( k, v, |k, v, _a| f ( k, v) , |_k, a| a)
1262
+ }
1263
+
1264
+ /// Modify and return the value corresponding to the key in the map, or
1265
+ /// insert and return a new value if it doesn't exist.
1266
+ ///
1267
+ /// This method allows for all insertion behaviours of a hashmap;
1268
+ /// see methods like `insert`, `find_or_insert` and
1269
+ /// `insert_or_update_with` for less general and more friendly
1270
+ /// variations of this.
1271
+ ///
1272
+ /// # Example
1273
+ ///
1274
+ /// ```rust
1275
+ /// use collections::HashMap;
1276
+ ///
1277
+ /// // map some strings to vectors of strings
1278
+ /// let mut map = HashMap::new();
1279
+ /// map.insert("a key", vec!["value"]);
1280
+ /// map.insert("z key", vec!["value"]);
1281
+ ///
1282
+ /// let new = vec!["a key", "b key", "z key"];
1283
+ ///
1284
+ /// for k in new.move_iter() {
1285
+ /// map.find_with_or_insert_with(
1286
+ /// k, "new value",
1287
+ /// // if the key does exist either prepend or append this
1288
+ /// // new value based on the first letter of the key.
1289
+ /// |key, already, new| {
1290
+ /// if key.as_slice().starts_with("z") {
1291
+ /// already.unshift(new);
1292
+ /// } else {
1293
+ /// already.push(new);
1294
+ /// }
1295
+ /// },
1296
+ /// // if the key doesn't exist in the map yet, add it in
1297
+ /// // the obvious way.
1298
+ /// |_k, v| vec![v]);
1299
+ /// }
1300
+ ///
1301
+ /// assert_eq!(map.len(), 3);
1302
+ /// assert_eq!(map.get(&"a key"), &vec!["value", "new value"]);
1303
+ /// assert_eq!(map.get(&"b key"), &vec!["new value"]);
1304
+ /// assert_eq!(map.get(&"z key"), &vec!["new value", "value"]);
1305
+ /// ```
1306
+ pub fn find_with_or_insert_with < ' a , A > ( & ' a mut self ,
1307
+ k : K ,
1308
+ a : A ,
1309
+ found : |& K , & mut V , A |,
1310
+ not_found: |& K , A | -> V )
1311
+ -> & ' a mut V {
1278
1312
let hash = self . make_hash ( & k) ;
1279
1313
match self . search_hashed ( & hash, & k) {
1280
- None => self . insert_hashed ( hash, k, v) ,
1314
+ None => {
1315
+ let v = not_found ( & k, a) ;
1316
+ self . insert_hashed ( hash, k, v)
1317
+ } ,
1281
1318
Some ( idx) => {
1282
1319
let ( _, v_ref) = self . table . read_mut ( & idx) ;
1283
- f ( & k, v_ref) ;
1320
+ found ( & k, v_ref, a ) ;
1284
1321
v_ref
1285
1322
}
1286
1323
}
0 commit comments