diff --git a/src/core_iterators.rs b/src/core_iterators.rs
index be9a68d..9a2f541 100644
--- a/src/core_iterators.rs
+++ b/src/core_iterators.rs
@@ -30,56 +30,97 @@
 //!
 //! Usually you don't need to explicitly `use` any of the types declared here.
 
+use core::iter::FusedIterator;
+
 #[cfg(not(feature = "std"))]
 pub(crate) mod std {
     pub use ::alloc::vec;
     pub use core::*;
 }
 
-use std::hash::Hash;
+/// A draining iterator in arbitrary order over the couples
+/// `(item, priority)` in the queue.
+///
+/// It can be obtained calling the `drain` method.
+pub struct Drain<'a, I: 'a, P: 'a> {
+    pub(crate) iter: ::indexmap::map::Drain<'a, I, P>,
+}
+
+impl<'a, I: 'a, P: 'a> Iterator for Drain<'a, I, P> {
+    type Item = (I, P);
+    fn next(&mut self) -> Option<(I, P)> {
+        self.iter.next()
+    }
+}
+
+impl<I, P> DoubleEndedIterator for Drain<'_, I, P> {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.iter.next_back()
+    }
+}
+
+impl<I, P> ExactSizeIterator for Drain<'_, I, P> {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+}
+
+impl<I, P> FusedIterator for Drain<'_, I, P> {}
 
 /// An iterator in arbitrary order over the couples
 /// `(item, priority)` in the queue.
 ///
 /// It can be obtained calling the `iter` method.
-pub struct Iter<'a, I: 'a, P: 'a>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+pub struct Iter<'a, I: 'a, P: 'a> {
     pub(crate) iter: ::indexmap::map::Iter<'a, I, P>,
 }
 
-impl<'a, I: 'a, P: 'a> Iterator for Iter<'a, I, P>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+impl<'a, I: 'a, P: 'a> Iterator for Iter<'a, I, P> {
     type Item = (&'a I, &'a P);
     fn next(&mut self) -> Option<(&'a I, &'a P)> {
         self.iter.next()
     }
 }
 
+impl<I, P> DoubleEndedIterator for Iter<'_, I, P> {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.iter.next_back()
+    }
+}
+
+impl<I, P> ExactSizeIterator for Iter<'_, I, P> {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+}
+
+impl<I, P> FusedIterator for Iter<'_, I, P> {}
+
 /// An iterator in arbitrary order over the couples
 /// `(item, priority)` that consumes the queue.
 ///
 /// It can be obtained calling the `into_iter` method from the `IntoIterator` trait.
-pub struct IntoIter<I, P>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+pub struct IntoIter<I, P> {
     pub(crate) iter: ::indexmap::map::IntoIter<I, P>,
 }
 
-impl<I, P> Iterator for IntoIter<I, P>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+impl<I, P> Iterator for IntoIter<I, P> {
     type Item = (I, P);
     fn next(&mut self) -> Option<(I, P)> {
         self.iter.next()
     }
 }
+
+impl<I, P> DoubleEndedIterator for IntoIter<I, P> {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.iter.next_back()
+    }
+}
+
+impl<I, P> ExactSizeIterator for IntoIter<I, P> {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+}
+
+impl<I, P> FusedIterator for IntoIter<I, P> {}
diff --git a/src/double_priority_queue/iterators.rs b/src/double_priority_queue/iterators.rs
index d27e577..7c29ba6 100644
--- a/src/double_priority_queue/iterators.rs
+++ b/src/double_priority_queue/iterators.rs
@@ -36,10 +36,9 @@ pub(crate) mod std {
 }
 
 use core::hash::BuildHasher;
-use std::cmp::{Eq, Ord};
+use std::cmp::Ord;
 #[cfg(feature = "std")]
 use std::collections::hash_map::RandomState;
-use std::hash::Hash;
 use std::iter::*;
 
 use crate::DoublePriorityQueue;
@@ -58,7 +57,6 @@ use crate::DoublePriorityQueue;
 #[cfg(feature = "std")]
 pub struct IterMut<'a, I: 'a, P: 'a, H: 'a = RandomState>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     pq: &'a mut DoublePriorityQueue<I, P, H>,
@@ -68,7 +66,6 @@ where
 #[cfg(not(feature = "std"))]
 pub struct IterMut<'a, I: 'a, P: 'a, H: 'a>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     pq: &'a mut DoublePriorityQueue<I, P, H>,
@@ -77,7 +74,6 @@ where
 
 impl<'a, I: 'a, P: 'a, H: 'a> IterMut<'a, I, P, H>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     pub(crate) fn new(pq: &'a mut DoublePriorityQueue<I, P, H>) -> Self {
@@ -87,7 +83,6 @@ where
 
 impl<'a, 'b: 'a, I: 'a, P: 'a, H: 'a> Iterator for IterMut<'a, I, P, H>
 where
-    I: Hash + Eq,
     P: Ord,
     H: BuildHasher,
 {
@@ -106,9 +101,44 @@ where
     }
 }
 
+impl<'a, 'b: 'a, I: 'a, P: 'a, H: 'a> DoubleEndedIterator for IterMut<'a, I, P, H>
+where
+    P: Ord,
+    H: BuildHasher,
+{
+    fn next_back(&mut self) -> Option<Self::Item> {
+        use indexmap::map::MutableKeys;
+        let r: Option<(&'a mut I, &'a mut P)> = self
+            .pq
+            .store
+            .map
+            .get_index_mut2(self.pos)
+            .map(|(i, p)| (i as *mut I, p as *mut P))
+            .map(|(i, p)| unsafe { (i.as_mut().unwrap(), p.as_mut().unwrap()) });
+        self.pos -= 1;
+        r
+    }
+}
+
+impl<'a, I, P, H> ExactSizeIterator for IterMut<'_, I, P, H>
+where
+    P: Ord,
+    H: BuildHasher,
+{
+    fn len(&self) -> usize {
+        self.pq.len()
+    }
+}
+
+impl<'a, I, P, H> FusedIterator for IterMut<'_, I, P, H>
+where
+    P: Ord,
+    H: BuildHasher,
+{
+}
+
 impl<'a, I: 'a, P: 'a, H: 'a> Drop for IterMut<'a, I, P, H>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     fn drop(&mut self) {
@@ -127,7 +157,6 @@ where
 #[cfg(feature = "std")]
 pub struct IntoSortedIter<I, P, H = RandomState>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     pub(crate) pq: DoublePriorityQueue<I, P, H>,
@@ -136,7 +165,6 @@ where
 #[cfg(not(feature = "std"))]
 pub struct IntoSortedIter<I, P, H>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     pub(crate) pq: DoublePriorityQueue<I, P, H>,
@@ -144,7 +172,6 @@ where
 
 impl<I, P, H> Iterator for IntoSortedIter<I, P, H>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     type Item = (I, P);
@@ -155,10 +182,20 @@ where
 
 impl<I, P, H> DoubleEndedIterator for IntoSortedIter<I, P, H>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     fn next_back(&mut self) -> Option<(I, P)> {
         self.pq.pop_max()
     }
 }
+
+impl<I, P, H> ExactSizeIterator for IntoSortedIter<I, P, H>
+where
+    P: Ord,
+{
+    fn len(&self) -> usize {
+        self.pq.len()
+    }
+}
+
+impl<I, P, H> FusedIterator for IntoSortedIter<I, P, H> where P: Ord {}
diff --git a/src/double_priority_queue/mod.rs b/src/double_priority_queue/mod.rs
index dd09f91..e83b3fd 100644
--- a/src/double_priority_queue/mod.rs
+++ b/src/double_priority_queue/mod.rs
@@ -34,7 +34,7 @@ pub mod iterators;
 #[cfg(not(feature = "std"))]
 use std::vec::Vec;
 
-use crate::core_iterators::{IntoIter, Iter};
+use crate::core_iterators::*;
 use crate::store::{Index, Position, Store};
 use iterators::*;
 
@@ -88,21 +88,13 @@ use std::mem::replace;
 /// ```
 #[derive(Clone)]
 #[cfg(feature = "std")]
-pub struct DoublePriorityQueue<I, P, H = RandomState>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+pub struct DoublePriorityQueue<I, P, H = RandomState> {
     pub(crate) store: Store<I, P, H>,
 }
 
 #[derive(Clone)]
 #[cfg(not(feature = "std"))]
-pub struct DoublePriorityQueue<I, P, H>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+pub struct DoublePriorityQueue<I, P, H> {
     pub(crate) store: Store<I, P, H>,
 }
 
@@ -181,6 +173,17 @@ where
             store: Store::with_capacity_and_hasher(capacity, hash_builder),
         }
     }
+}
+
+impl<I, P, H> DoublePriorityQueue<I, P, H> {
+    /// Returns the number of elements the internal map can hold without
+    /// reallocating.
+    ///
+    /// This number is a lower bound; the map might be able to hold more,
+    /// but is guaranteed to be able to hold at least this many.
+    pub fn capacity(&self) -> usize {
+        self.store.capacity()
+    }
 
     /// Returns an iterator in arbitrary order over the
     /// (item, priority) elements in the queue
@@ -188,17 +191,59 @@ where
         self.store.iter()
     }
 
+    /// Clears the PriorityQueue, returning an iterator over the removed elements in arbitrary order.
+    /// If the iterator is dropped before being fully consumed, it drops the remaining elements in arbitrary order.
+    pub fn drain(&mut self) -> Drain<I, P> {
+        self.store.drain()
+    }
+
     /// Shrinks the capacity of the internal data structures
     /// that support this operation as much as possible.
     pub fn shrink_to_fit(&mut self) {
         self.store.shrink_to_fit();
     }
-}
 
+    /// Returns the number of elements in the priority queue.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.store.len()
+    }
+
+    /// Returns true if the priority queue contains no elements.
+    pub fn is_empty(&self) -> bool {
+        self.store.is_empty()
+    }
+
+    /// Returns the couple (item, priority) with the lowest
+    /// priority in the queue, or None if it is empty.
+    ///
+    /// Computes in **O(1)** time
+    pub fn peek_min(&self) -> Option<(&I, &P)> {
+        self.find_min().and_then(|i| {
+            self.store
+                .map
+                .get_index(unsafe { *self.store.heap.get_unchecked(i.0) }.0)
+        })
+    }
+
+    // reserve_exact -> IndexMap does not implement reserve_exact
+
+    /// Reserves capacity for at least `additional` more elements to be inserted
+    /// in the given `DoublePriorityQueue`. The collection may reserve more space to avoid
+    /// frequent reallocations. After calling `reserve`, capacity will be
+    /// greater than or equal to `self.len() + additional`. Does nothing if
+    /// capacity is already sufficient.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new capacity overflows `usize`.
+    pub fn reserve(&mut self, additional: usize) {
+        self.store.reserve(additional);
+    }
+}
 impl<I, P, H> DoublePriorityQueue<I, P, H>
 where
     P: Ord,
-    I: Hash + Eq,
 {
     /// Return an iterator in arbitrary order over the
     /// (item, priority) elements in the queue.
@@ -214,18 +259,6 @@ where
         IterMut::new(self)
     }
 
-    /// Returns the couple (item, priority) with the lowest
-    /// priority in the queue, or None if it is empty.
-    ///
-    /// Computes in **O(1)** time
-    pub fn peek_min(&self) -> Option<(&I, &P)> {
-        self.find_min().and_then(|i| {
-            self.store
-                .map
-                .get_index(unsafe { *self.store.heap.get_unchecked(i.0) }.0)
-        })
-    }
-
     /// Returns the couple (item, priority) with the greatest
     /// priority in the queue, or None if it is empty.
     ///
@@ -238,15 +271,6 @@ where
         })
     }
 
-    /// Returns the number of elements the internal map can hold without
-    /// reallocating.
-    ///
-    /// This number is a lower bound; the map might be able to hold more,
-    /// but is guaranteed to be able to hold at least this many.
-    pub fn capacity(&self) -> usize {
-        self.store.capacity()
-    }
-
     /// Removes the item with the lowest priority from
     /// the priority queue and returns the pair (item, priority),
     /// or None if the queue is empty.
@@ -295,17 +319,6 @@ where
         res
     }
 
-    /// Returns the number of elements in the priority queue.
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.store.len()
-    }
-
-    /// Returns true if the priority queue contains no elements.
-    pub fn is_empty(&self) -> bool {
-        self.store.is_empty()
-    }
-
     /// Generates a new double ended iterator from self that
     /// will extract the elements from the one with the lowest priority
     /// to the highest one.
@@ -316,25 +329,66 @@ where
 
 impl<I, P, H> DoublePriorityQueue<I, P, H>
 where
-    P: Ord,
-    I: Hash + Eq,
     H: BuildHasher,
 {
-    // reserve_exact -> IndexMap does not implement reserve_exact
+    /// Returns the couple (item, priority) with the lowest
+    /// priority in the queue, or None if it is empty.
+    ///
+    /// The item is a mutable reference, but it's a logic error to modify it
+    /// in a way that change the result of  `Hash` or `Eq`.
+    ///
+    /// The priority cannot be modified with a call to this function.
+    /// To modify the priority use `push`, `change_priority` or
+    /// `change_priority_by`.
+    ///
+    /// Computes in **O(1)** time
+    pub fn peek_min_mut(&mut self) -> Option<(&mut I, &P)> {
+        use indexmap::map::MutableKeys;
 
-    /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the given `DoublePriorityQueue`. The collection may reserve more space to avoid
-    /// frequent reallocations. After calling `reserve`, capacity will be
-    /// greater than or equal to `self.len() + additional`. Does nothing if
-    /// capacity is already sufficient.
+        self.find_min()
+            .and_then(move |i| {
+                self.store
+                    .map
+                    .get_index_mut2(unsafe { *self.store.heap.get_unchecked(i.0) }.0)
+            })
+            .map(|(k, v)| (k, &*v))
+    }
+}
+
+impl<I, P, H> DoublePriorityQueue<I, P, H>
+where
+    P: Ord,
+    H: BuildHasher,
+{
+    /// Returns the couple (item, priority) with the greatest
+    /// priority in the queue, or None if it is empty.
     ///
-    /// # Panics
+    /// The item is a mutable reference, but it's a logic error to modify it
+    /// in a way that change the result of  `Hash` or `Eq`.
     ///
-    /// Panics if the new capacity overflows `usize`.
-    pub fn reserve(&mut self, additional: usize) {
-        self.store.reserve(additional);
+    /// The priority cannot be modified with a call to this function.
+    /// To modify the priority use `push`, `change_priority` or
+    /// `change_priority_by`.
+    ///
+    /// Computes in **O(1)** time
+    pub fn peek_max_mut(&mut self) -> Option<(&mut I, &P)> {
+        use indexmap::map::MutableKeys;
+        self.find_max()
+            .and_then(move |i| {
+                self.store
+                    .map
+                    .get_index_mut2(unsafe { *self.store.heap.get_unchecked(i.0) }.0)
+            })
+            .map(|(k, v)| (k, &*v))
     }
+}
 
+impl<I, P, H> DoublePriorityQueue<I, P, H>
+where
+    P: Ord,
+    I: Hash + Eq,
+    H: BuildHasher,
+{
     /// Insert the item-priority pair into the queue.
     ///
     /// If an element equal to `item` was already into the queue,
@@ -437,51 +491,6 @@ where
             })
     }
 
-    /// Returns the couple (item, priority) with the lowest
-    /// priority in the queue, or None if it is empty.
-    ///
-    /// The item is a mutable reference, but it's a logic error to modify it
-    /// in a way that change the result of  `Hash` or `Eq`.
-    ///
-    /// The priority cannot be modified with a call to this function.
-    /// To modify the priority use `push`, `change_priority` or
-    /// `change_priority_by`.
-    ///
-    /// Computes in **O(1)** time
-    pub fn peek_min_mut(&mut self) -> Option<(&mut I, &P)> {
-        use indexmap::map::MutableKeys;
-
-        self.find_min()
-            .and_then(move |i| {
-                self.store
-                    .map
-                    .get_index_mut2(unsafe { *self.store.heap.get_unchecked(i.0) }.0)
-            })
-            .map(|(k, v)| (k, &*v))
-    }
-
-    /// Returns the couple (item, priority) with the greatest
-    /// priority in the queue, or None if it is empty.
-    ///
-    /// The item is a mutable reference, but it's a logic error to modify it
-    /// in a way that change the result of  `Hash` or `Eq`.
-    ///
-    /// The priority cannot be modified with a call to this function.
-    /// To modify the priority use `push`, `change_priority` or
-    /// `change_priority_by`.
-    ///
-    /// Computes in **O(1)** time
-    pub fn peek_max_mut(&mut self) -> Option<(&mut I, &P)> {
-        use indexmap::map::MutableKeys;
-        self.find_max()
-            .and_then(move |i| {
-                self.store
-                    .map
-                    .get_index_mut2(unsafe { *self.store.heap.get_unchecked(i.0) }.0)
-            })
-            .map(|(k, v)| (k, &*v))
-    }
-
     /// Change the priority of an Item using the provided function.
     /// Return a boolean value where `true` means the item was in the queue and update was successful
     ///
@@ -582,17 +591,19 @@ where
     }
 }
 
-impl<I, P, H> DoublePriorityQueue<I, P, H>
-where
-    P: Ord,
-    I: Hash + Eq,
-{
+impl<I, P, H> DoublePriorityQueue<I, P, H> {
+    /// Returns the index of the min element
+    fn find_min(&self) -> Option<Position> {
+        match self.len() {
+            0 => None,
+            _ => Some(Position(0)),
+        }
+    }
 }
 
 impl<I, P, H> DoublePriorityQueue<I, P, H>
 where
     P: Ord,
-    I: Hash + Eq,
 {
     /**************************************************************************/
     /*                            internal functions                          */
@@ -805,14 +816,6 @@ where
             ),
         }
     }
-
-    /// Returns the index of the min element
-    fn find_min(&self) -> Option<Position> {
-        match self.len() {
-            0 => None,
-            _ => Some(Position(0)),
-        }
-    }
 }
 
 //FIXME: fails when the vector contains repeated items
diff --git a/src/priority_queue/iterators.rs b/src/priority_queue/iterators.rs
index e2d1c0b..30f5f08 100644
--- a/src/priority_queue/iterators.rs
+++ b/src/priority_queue/iterators.rs
@@ -36,10 +36,9 @@ pub(crate) mod std {
 }
 
 use core::hash::BuildHasher;
-use std::cmp::{Eq, Ord};
+use std::cmp::Ord;
 #[cfg(feature = "std")]
 use std::collections::hash_map::RandomState;
-use std::hash::Hash;
 use std::iter::*;
 
 use crate::PriorityQueue;
@@ -58,7 +57,6 @@ use crate::PriorityQueue;
 #[cfg(feature = "std")]
 pub struct IterMut<'a, I: 'a, P: 'a, H: 'a = RandomState>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     pq: &'a mut PriorityQueue<I, P, H>,
@@ -68,7 +66,6 @@ where
 #[cfg(not(feature = "std"))]
 pub struct IterMut<'a, I: 'a, P: 'a, H: 'a>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     pq: &'a mut PriorityQueue<I, P, H>,
@@ -77,7 +74,6 @@ where
 
 impl<'a, I: 'a, P: 'a, H: 'a> IterMut<'a, I, P, H>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     pub(crate) fn new(pq: &'a mut PriorityQueue<I, P, H>) -> Self {
@@ -87,7 +83,6 @@ where
 
 impl<'a, 'b: 'a, I: 'a, P: 'a, H: 'a> Iterator for IterMut<'a, I, P, H>
 where
-    I: Hash + Eq,
     P: Ord,
     H: BuildHasher,
 {
@@ -109,7 +104,6 @@ where
 
 impl<'a, I: 'a, P: 'a, H: 'a> Drop for IterMut<'a, I, P, H>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     fn drop(&mut self) {
@@ -122,26 +116,17 @@ where
 ///
 /// It can be obtained calling the `into_sorted_iter` method.
 #[cfg(feature = "std")]
-pub struct IntoSortedIter<I, P, H = RandomState>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+pub struct IntoSortedIter<I, P, H = RandomState> {
     pub(crate) pq: PriorityQueue<I, P, H>,
 }
 
 #[cfg(not(feature = "std"))]
-pub struct IntoSortedIter<I, P, H>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+pub struct IntoSortedIter<I, P, H> {
     pub(crate) pq: PriorityQueue<I, P, H>,
 }
 
 impl<I, P, H> Iterator for IntoSortedIter<I, P, H>
 where
-    I: Hash + Eq,
     P: Ord,
 {
     type Item = (I, P);
diff --git a/src/priority_queue/mod.rs b/src/priority_queue/mod.rs
index 70ac22c..a9f351d 100644
--- a/src/priority_queue/mod.rs
+++ b/src/priority_queue/mod.rs
@@ -35,7 +35,7 @@ pub mod iterators;
 #[cfg(not(feature = "std"))]
 use std::vec::Vec;
 
-use crate::core_iterators::{IntoIter, Iter};
+use crate::core_iterators::*;
 use crate::store::{Index, Position, Store};
 use iterators::*;
 
@@ -79,21 +79,13 @@ use std::mem::replace;
 /// ```
 #[derive(Clone, Debug)]
 #[cfg(feature = "std")]
-pub struct PriorityQueue<I, P, H = RandomState>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+pub struct PriorityQueue<I, P, H = RandomState> {
     pub(crate) store: Store<I, P, H>,
 }
 
 #[derive(Clone, Debug)]
 #[cfg(not(feature = "std"))]
-pub struct PriorityQueue<I, P, H>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+pub struct PriorityQueue<I, P, H> {
     pub(crate) store: Store<I, P, H>,
 }
 
@@ -172,7 +164,9 @@ where
             store: Store::with_capacity_and_hasher(capacity, hash_builder),
         }
     }
+}
 
+impl<I, P, H> PriorityQueue<I, P, H> {
     /// Returns an iterator in arbitrary order over the
     /// (item, priority) elements in the queue
     pub fn iter(&self) -> Iter<I, P> {
@@ -184,25 +178,11 @@ where
     pub fn shrink_to_fit(&mut self) {
         self.store.shrink_to_fit();
     }
-}
 
-impl<I, P, H> PriorityQueue<I, P, H>
-where
-    P: Ord,
-    I: Hash + Eq,
-{
-    /// Returns an iterator in arbitrary order over the
-    /// (item, priority) elements in the queue.
-    ///
-    /// The item and the priority are mutable references, but it's a logic error
-    /// to modify the item in a way that change the result of `Hash` or `Eq`.
-    ///
-    /// It's *not* an error, instead, to modify the priorities, because the heap
-    /// will be rebuilt once the `IterMut` goes out of scope. It would be
-    /// rebuilt even if no priority value would have been modified, but the
-    /// procedure will not move anything, but just compare the priorities.
-    pub fn iter_mut(&mut self) -> IterMut<I, P, H> {
-        IterMut::new(self)
+    /// Clears the PriorityQueue, returning an iterator over the removed elements in arbitrary order.
+    /// If the iterator is dropped before being fully consumed, it drops the remaining elements in arbitrary order.
+    pub fn drain(&mut self) -> Drain<I, P> {
+        self.store.drain()
     }
 
     /// Returns the couple (item, priority) with the greatest
@@ -225,6 +205,59 @@ where
         self.store.capacity()
     }
 
+    /// Returns the number of elements in the priority queue.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.store.len()
+    }
+
+    /// Returns true if the priority queue contains no elements.
+    pub fn is_empty(&self) -> bool {
+        self.store.is_empty()
+    }
+
+    /// Returns the items not ordered
+    pub fn into_vec(self) -> Vec<I> {
+        self.store.into_vec()
+    }
+
+    /// Drops all items from the priority queue
+    pub fn clear(&mut self) {
+        self.store.clear();
+    }
+
+    /// Reserves capacity for at least `additional` more elements to be inserted
+    /// in the given `PriorityQueue`. The collection may reserve more space to avoid
+    /// frequent reallocations. After calling `reserve`, capacity will be
+    /// greater than or equal to `self.len() + additional`. Does nothing if
+    /// capacity is already sufficient.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new capacity overflows `usize`.
+    pub fn reserve(&mut self, additional: usize) {
+        self.store.reserve(additional);
+    }
+}
+
+impl<I, P, H> PriorityQueue<I, P, H>
+where
+    P: Ord,
+{
+    /// Returns an iterator in arbitrary order over the
+    /// (item, priority) elements in the queue.
+    ///
+    /// The item and the priority are mutable references, but it's a logic error
+    /// to modify the item in a way that change the result of `Hash` or `Eq`.
+    ///
+    /// It's *not* an error, instead, to modify the priorities, because the heap
+    /// will be rebuilt once the `IterMut` goes out of scope. It would be
+    /// rebuilt even if no priority value would have been modified, but the
+    /// procedure will not move anything, but just compare the priorities.
+    pub fn iter_mut(&mut self) -> IterMut<I, P, H> {
+        IterMut::new(self)
+    }
+
     /// Removes the item with the greatest priority from
     /// the priority queue and returns the pair (item, priority),
     /// or None if the queue is empty.
@@ -251,17 +284,6 @@ where
         res
     }
 
-    /// Returns the number of elements in the priority queue.
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.store.len()
-    }
-
-    /// Returns true if the priority queue contains no elements.
-    pub fn is_empty(&self) -> bool {
-        self.store.is_empty()
-    }
-
     /// Generates a new iterator from self that
     /// will extract the elements from the one with the highest priority
     /// to the lowest one.
@@ -278,19 +300,6 @@ where
 {
     // reserve_exact -> IndexMap does not implement reserve_exact
 
-    /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the given `PriorityQueue`. The collection may reserve more space to avoid
-    /// frequent reallocations. After calling `reserve`, capacity will be
-    /// greater than or equal to `self.len() + additional`. Does nothing if
-    /// capacity is already sufficient.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the new capacity overflows `usize`.
-    pub fn reserve(&mut self, additional: usize) {
-        self.store.reserve(additional);
-    }
-
     /// Insert the item-priority pair into the queue.
     ///
     /// If an element equal to `item` was already into the queue,
@@ -491,16 +500,6 @@ where
         })
     }
 
-    /// Returns the items not ordered
-    pub fn into_vec(self) -> Vec<I> {
-        self.store.into_vec()
-    }
-
-    /// Drops all items from the priority queue
-    pub fn clear(&mut self) {
-        self.store.clear();
-    }
-
     /// Move all items of the `other` queue to `self`
     /// ignoring the items Eq to elements already in `self`
     /// At the end, `other` will be empty.
@@ -524,7 +523,6 @@ where
 impl<I, P, H> PriorityQueue<I, P, H>
 where
     P: Ord,
-    I: Hash + Eq,
 {
     /**************************************************************************/
     /*                            internal functions                          */
diff --git a/src/store.rs b/src/store.rs
index 9b6ae5a..7391f72 100644
--- a/src/store.rs
+++ b/src/store.rs
@@ -52,11 +52,7 @@ pub(crate) struct Position(pub usize);
 /// Internal storage of PriorityQueue and DoublePriorityQueue
 #[derive(Clone)]
 #[cfg(feature = "std")]
-pub(crate) struct Store<I, P, H = RandomState>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+pub(crate) struct Store<I, P, H = RandomState> {
     pub map: IndexMap<I, P, H>, // Stores the items and assign them an index
     pub heap: Vec<Index>,       // Implements the heap of indexes
     pub qp: Vec<Position>,      // Performs the translation from the index
@@ -66,11 +62,7 @@ where
 
 #[derive(Clone)]
 #[cfg(not(feature = "std"))]
-pub(crate) struct Store<I, P, H>
-where
-    I: Hash + Eq,
-    P: Ord,
-{
+pub(crate) struct Store<I, P, H> {
     pub map: IndexMap<I, P, H>, // Stores the items and assign them an index
     pub heap: Vec<Index>,       // Implements the heap of indexes
     pub qp: Vec<Position>,      // Performs the translation from the index
@@ -139,7 +131,9 @@ where
             size: 0,
         }
     }
+}
 
+impl<I, P, H> Store<I, P, H> {
     /// Returns an iterator in arbitrary order over the
     /// (item, priority) elements in the queue
     pub fn iter(&self) -> Iter<I, P> {
@@ -172,13 +166,19 @@ where
         self.heap.reserve(additional);
         self.qp.reserve(additional);
     }
-}
 
-impl<I, P, H> Store<I, P, H>
-where
-    P: Ord,
-    I: Hash + Eq,
-{
+    /// Clears the store, returning an iterator over the removed elements in arbitrary order.
+    /// If the iterator is dropped before being fully consumed, it drops the remaining elements in arbitrary order.
+    pub fn drain(&mut self) -> Drain<'_, I, P> {
+        self.heap.clear();
+        self.qp.clear();
+        self.size = 0;
+
+        Drain {
+            iter: self.map.drain(..),
+        }
+    }
+
     /// Returns the number of elements the internal map can hold without
     /// reallocating.
     ///
@@ -201,6 +201,19 @@ where
         self.size == 0
     }
 
+    /// Returns the items not ordered
+    pub fn into_vec(self) -> Vec<I> {
+        self.map.into_iter().map(|(i, _)| i).collect()
+    }
+
+    /// Drops all items from the priority queue
+    pub fn clear(&mut self) {
+        self.heap.clear();
+        self.qp.clear();
+        self.map.clear();
+        self.size = 0;
+    }
+
     /// Swap two elements keeping a consistent state.
     ///
     /// Computes in **O(1)** time
@@ -378,19 +391,6 @@ where
         })
     }
 
-    /// Returns the items not ordered
-    pub fn into_vec(self) -> Vec<I> {
-        self.map.into_iter().map(|(i, _)| i).collect()
-    }
-
-    /// Drops all items from the priority queue
-    pub fn clear(&mut self) {
-        self.heap.clear();
-        self.qp.clear();
-        self.map.clear();
-        self.size = 0;
-    }
-
     /// Move all items of the `other` queue to `self`
     /// ignoring the items Eq to elements already in `self`
     /// At the end, `other` will be empty.
@@ -405,10 +405,9 @@ where
         if other.size == 0 {
             return;
         }
-        let drain = other.map.drain(..);
         // what should we do for duplicated keys?
         // ignore
-        for (k, v) in drain {
+        for (k, v) in other.drain() {
             if !self.map.contains_key(&k) {
                 let i = self.size;
                 self.map.insert(k, v);
@@ -417,16 +416,10 @@ where
                 self.size += 1;
             }
         }
-        other.clear();
     }
 }
 
-impl<I, P, H> IntoIterator for Store<I, P, H>
-where
-    I: Hash + Eq,
-    P: Ord,
-    H: BuildHasher,
-{
+impl<I, P, H> IntoIterator for Store<I, P, H> {
     type Item = (I, P);
     type IntoIter = IntoIter<I, P>;
     fn into_iter(self) -> IntoIter<I, P> {
@@ -436,12 +429,7 @@ where
     }
 }
 
-impl<'a, I, P, H> IntoIterator for &'a Store<I, P, H>
-where
-    I: Hash + Eq,
-    P: Ord,
-    H: BuildHasher,
-{
+impl<'a, I, P, H> IntoIterator for &'a Store<I, P, H> {
     type Item = (&'a I, &'a P);
     type IntoIter = Iter<'a, I, P>;
     fn into_iter(self) -> Iter<'a, I, P> {
@@ -550,8 +538,8 @@ where
 use std::fmt;
 impl<I, P, H> fmt::Debug for Store<I, P, H>
 where
-    I: fmt::Debug + Hash + Eq,
-    P: fmt::Debug + Ord,
+    I: fmt::Debug,
+    P: fmt::Debug,
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_map()
@@ -575,12 +563,7 @@ mod serde {
 
     use serde::ser::{Serialize, SerializeSeq, Serializer};
 
-    impl<I, P, H> Serialize for Store<I, P, H>
-    where
-        I: Hash + Eq + Serialize,
-        P: Ord + Serialize,
-        H: BuildHasher,
-    {
+    impl<I, P, H> Serialize for Store<I, P, H> {
         fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
         where
             S: Serializer,
diff --git a/tests/double_priority_queue.rs b/tests/double_priority_queue.rs
index 4d3b280..149de1e 100644
--- a/tests/double_priority_queue.rs
+++ b/tests/double_priority_queue.rs
@@ -343,6 +343,24 @@ mod doublepq_tests {
         }
     }
 
+    #[test]
+    fn drain() {
+        use std::collections::hash_map::RandomState;
+        let mut queue = DoublePriorityQueue::<i32, i32, RandomState>::default();
+
+        for i in 0..7 {
+            queue.push(i, i);
+        }
+
+        let previous_capacity = queue.capacity();
+        queue.drain();
+
+        assert_eq!(queue.len(), 0);
+        assert_eq!(queue.capacity(), previous_capacity);
+        assert_eq!(queue.pop_min(), None);
+        assert_eq!(queue.pop_max(), None);
+    }
+
     #[test]
     fn extend() {
         let mut pq = DoublePriorityQueue::new();
diff --git a/tests/priority_queue.rs b/tests/priority_queue.rs
index 9acf62d..127591f 100644
--- a/tests/priority_queue.rs
+++ b/tests/priority_queue.rs
@@ -327,6 +327,23 @@ mod pqueue_tests {
         }
     }
 
+    #[test]
+    fn drain() {
+        use std::collections::hash_map::RandomState;
+        let mut queue = PriorityQueue::<i32, i32, RandomState>::default();
+
+        for i in 0..7 {
+            queue.push(i, i);
+        }
+
+        let previous_capacity = queue.capacity();
+        queue.drain();
+
+        assert_eq!(queue.len(), 0);
+        assert_eq!(queue.capacity(), previous_capacity);
+        assert_eq!(queue.pop(), None);
+    }
+
     #[test]
     fn extend() {
         let mut pq = PriorityQueue::new();