diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 662ae913764f4..cc7bb8600b98d 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -20,7 +20,7 @@ use cmp::{max, Eq, Equiv, PartialEq};
 use default::Default;
 use fmt::{mod, Show};
 use hash::{Hash, Hasher, RandomSipHasher};
-use iter::{mod, Iterator, FromIterator, Extend};
+use iter::{mod, Iterator, DoubleEndedIterator, ExactSize, FromIterator, Extend};
 use kinds::Sized;
 use mem::{mod, replace};
 use num::UnsignedInt;
@@ -1325,6 +1325,15 @@ impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
     }
 }
 
+impl<'a, K, V> DoubleEndedIterator<(&'a K, &'a V)> for Entries<'a, K, V> {
+    #[inline]
+    fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
+        self.inner.next_back()
+    }
+}
+
+impl<'a, K, V> ExactSize<(&'a K, &'a V)> for Entries<'a, K, V> {}
+
 impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
     #[inline]
     fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
@@ -1336,6 +1345,15 @@ impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
     }
 }
 
+impl<'a, K, V> DoubleEndedIterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
+    #[inline]
+    fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
+        self.inner.next_back()
+    }
+}
+
+impl<'a, K, V> ExactSize<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {}
+
 impl<K, V> Iterator<(K, V)> for MoveEntries<K, V> {
     #[inline]
     fn next(&mut self) -> Option<(K, V)> {
@@ -1347,6 +1365,15 @@ impl<K, V> Iterator<(K, V)> for MoveEntries<K, V> {
     }
 }
 
+impl<K, V> DoubleEndedIterator<(K, V)> for MoveEntries<K, V> {
+    #[inline]
+    fn next_back(&mut self) -> Option<(K, V)> {
+        self.inner.next_back()
+    }
+}
+
+impl<K, V> ExactSize<(K, V)> for MoveEntries<K, V> {}
+
 impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// Gets a reference to the value in the entry
     pub fn get(&self) -> &V {
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index f41ccea0aaf03..919d5b63245e2 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -15,7 +15,7 @@ pub use self::BucketState::*;
 use clone::Clone;
 use cmp;
 use hash::{Hash, Hasher};
-use iter::{Iterator, count};
+use iter::{Iterator, DoubleEndedIterator, ExactSize, count};
 use kinds::{Sized, marker};
 use mem::{min_align_of, size_of};
 use mem;
@@ -620,6 +620,25 @@ impl<K, V> RawTable<K, V> {
         }
     }
 
+    fn one_past_last_bucket_raw(&self) -> RawBucket<K, V> {
+        let hashes_size = self.capacity * size_of::<u64>();
+        let keys_size = self.capacity * size_of::<K>();
+        let vals_size = self.capacity * size_of::<V>();
+
+        let buffer = self.hashes as *mut u8;
+        let (keys_offset, vals_offset) = calculate_offsets(hashes_size,
+                                                           keys_size, min_align_of::<K>(),
+                                                           min_align_of::<V>());
+
+        unsafe {
+            RawBucket {
+                hash: self.hashes.offset(hashes_size as int),
+                key:  buffer.offset(keys_offset as int + keys_size as int) as *mut K,
+                val:  buffer.offset(vals_offset as int + vals_size as int) as *mut V
+            }
+        }
+    }
+
     /// Creates a new raw table from a given capacity. All buckets are
     /// initially empty.
     #[allow(experimental)]
@@ -644,10 +663,8 @@ impl<K, V> RawTable<K, V> {
 
     fn raw_buckets(&self) -> RawBuckets<K, V> {
         RawBuckets {
-            raw: self.first_bucket_raw(),
-            hashes_end: unsafe {
-                self.hashes.offset(self.capacity as int)
-            },
+            start: self.first_bucket_raw(),
+            end:   self.one_past_last_bucket_raw(),
             marker: marker::ContravariantLifetime,
         }
     }
@@ -667,12 +684,12 @@ impl<K, V> RawTable<K, V> {
     }
 
     pub fn into_iter(self) -> MoveEntries<K, V> {
-        let RawBuckets { raw, hashes_end, .. } = self.raw_buckets();
+        let RawBuckets { start, end, .. } = self.raw_buckets();
         // Replace the marker regardless of lifetime bounds on parameters.
         MoveEntries {
             iter: RawBuckets {
-                raw: raw,
-                hashes_end: hashes_end,
+                start:  start,
+                end:    end,
                 marker: marker::ContravariantLifetime,
             },
             table: self,
@@ -695,18 +712,18 @@ impl<K, V> RawTable<K, V> {
 /// A raw iterator. The basis for some other iterators in this module. Although
 /// this interface is safe, it's not used outside this module.
 struct RawBuckets<'a, K, V> {
-    raw: RawBucket<K, V>,
-    hashes_end: *mut u64,
+    start: RawBucket<K, V>,
+    end:   RawBucket<K, V>, // points one after the end.
     marker: marker::ContravariantLifetime<'a>,
 }
 
 impl<'a, K, V> Iterator<RawBucket<K, V>> for RawBuckets<'a, K, V> {
     fn next(&mut self) -> Option<RawBucket<K, V>> {
-        while self.raw.hash != self.hashes_end {
+        while self.start.hash != self.end.hash {
             unsafe {
                 // We are swapping out the pointer to a bucket and replacing
                 // it with the pointer to the next one.
-                let prev = ptr::replace(&mut self.raw, self.raw.offset(1));
+                let prev = ptr::replace(&mut self.start, self.start.offset(1));
                 if *prev.hash != EMPTY_BUCKET {
                     return Some(prev);
                 }
@@ -717,6 +734,21 @@ impl<'a, K, V> Iterator<RawBucket<K, V>> for RawBuckets<'a, K, V> {
     }
 }
 
+impl<'a, K, V> DoubleEndedIterator<RawBucket<K, V>> for RawBuckets<'a, K, V> {
+    fn next_back(&mut self) -> Option<RawBucket<K, V>> {
+        while self.start.hash != self.end.hash {
+            unsafe {
+                let next = ptr::replace(&mut self.end, self.end.offset(-1));
+                if *next.hash != EMPTY_BUCKET {
+                    return Some(next);
+                }
+            }
+        }
+
+        None
+    }
+}
+
 /// An iterator that moves out buckets in reverse order. It leaves the table
 /// in an inconsistent state and should only be used for dropping
 /// the table's remaining entries. It's used in the implementation of Drop.
@@ -785,6 +817,20 @@ impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
     }
 }
 
+impl<'a, K, V> DoubleEndedIterator<(&'a K, &'a V)> for Entries<'a, K, V> {
+    fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
+        self.iter.next_back().map(|bucket| {
+            self.elems_left += 1;
+            unsafe {
+                (&*bucket.key,
+                &*bucket.val)
+            }
+        })
+    }
+}
+
+impl<'a, K, V> ExactSize<(&'a K, &'a V)> for Entries<'a, K, V> {}
+
 impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
         self.iter.next().map(|bucket| {
@@ -801,6 +847,20 @@ impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
     }
 }
 
+impl<'a, K, V> DoubleEndedIterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
+    fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
+        self.iter.next().map(|bucket| {
+            self.elems_left += 1;
+            unsafe {
+                (&*bucket.key,
+                 &mut *bucket.val)
+            }
+        })
+    }
+}
+
+impl<'a, K, V> ExactSize<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {}
+
 impl<K, V> Iterator<(SafeHash, K, V)> for MoveEntries<K, V> {
     fn next(&mut self) -> Option<(SafeHash, K, V)> {
         self.iter.next().map(|bucket| {
@@ -823,6 +883,25 @@ impl<K, V> Iterator<(SafeHash, K, V)> for MoveEntries<K, V> {
     }
 }
 
+impl<K, V> DoubleEndedIterator<(SafeHash, K, V)> for MoveEntries<K, V> {
+    fn next_back(&mut self) -> Option<(SafeHash, K, V)> {
+        self.iter.next().map(|bucket| {
+            self.table.size += 1;
+            unsafe {
+                (
+                    SafeHash {
+                        hash: *bucket.hash,
+                    },
+                    ptr::read(bucket.key as *const K),
+                    ptr::read(bucket.val as *const V)
+                )
+            }
+        })
+    }
+}
+
+impl<K, V> ExactSize<(SafeHash, K, V)> for MoveEntries<K, V> {}
+
 impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
     fn clone(&self) -> RawTable<K, V> {
         unsafe {