@@ -274,6 +274,19 @@ impl<
274274 shard. write ( ) . remove ( hash, key)
275275 }
276276
277+ /// Remove an item from the cache whose key is `key` if `f(&value)` returns `true` for that entry.
278+ /// Compared to peek and remove, this method guarantees that no new value was inserted in-between.
279+ ///
280+ /// Returns the removed entry, if any.
281+ pub fn remove_if < Q , F > ( & self , key : & Q , f : F ) -> Option < ( Key , Val ) >
282+ where
283+ Q : Hash + Equivalent < Key > + ?Sized ,
284+ F : FnOnce ( & Val ) -> bool ,
285+ {
286+ let ( shard, hash) = self . shard_for ( key) . unwrap ( ) ;
287+ shard. write ( ) . remove_if ( hash, key, f)
288+ }
289+
277290 /// Inserts an item in the cache, but _only_ if an entry with key `key` already exists.
278291 /// If `soft` is set, the replace operation won't affect the "hotness" of the entry,
279292 /// even if the value is replaced.
@@ -756,4 +769,28 @@ mod tests {
756769 assert ! ( cache. len( ) <= 180 ) ;
757770 assert ! ( cache. weight( ) <= 200 ) ;
758771 }
772+
773+ #[ test]
774+ fn test_remove_if ( ) {
775+ let cache = Cache :: new ( 100 ) ;
776+
777+ // Insert test data
778+ cache. insert ( 1 , 10 ) ;
779+ cache. insert ( 2 , 20 ) ;
780+ cache. insert ( 3 , 30 ) ;
781+
782+ // Test removing with predicate that returns true
783+ let removed = cache. remove_if ( & 2 , |v| * v == 20 ) ;
784+ assert_eq ! ( removed, Some ( ( 2 , 20 ) ) ) ;
785+ assert_eq ! ( cache. get( & 2 ) , None ) ;
786+
787+ // Test removing with predicate that returns false
788+ let not_removed = cache. remove_if ( & 3 , |v| * v == 999 ) ;
789+ assert_eq ! ( not_removed, None ) ;
790+ assert_eq ! ( cache. get( & 3 ) , Some ( 30 ) ) ;
791+
792+ // Test removing non-existent key
793+ let not_found = cache. remove_if ( & 999 , |_| true ) ;
794+ assert_eq ! ( not_found, None ) ;
795+ }
759796}
0 commit comments