diff --git a/common/Makefile.am b/common/Makefile.am
index ff0c1315f0fa6499e57e6ad3aa5a3727bd661822..c7bb9f19d897a3c76c3c44d04c5b0ceaab9995a9 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -21,7 +21,7 @@ commoninclude_HEADERS = dlist.cc stdstreams.cc alignment.hh \
   gcd.hh lcm.hh configparser.hh propertymap.hh \
   collectivecommunication.hh mpihelper.hh singleton.hh \
   mpicollectivecommunication.hh geometrytype.hh utility.hh \
-  bartonnackmanifcheck.hh binaryfunctions.hh
+  bartonnackmanifcheck.hh binaryfunctions.hh lru.hh
 
 if EXPRESSIONTEMPLATES
 commoninclude_HEADERS += exprtmpl.hh exprtmpl/scalar.inc exprtmpl/exprexpr.inc
diff --git a/common/lru.hh b/common/lru.hh
new file mode 100644
index 0000000000000000000000000000000000000000..ca6032ee2780ee00d068fd8ae020e1c743777ed6
--- /dev/null
+++ b/common/lru.hh
@@ -0,0 +1,190 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_COMMON_LRU_HH
+#define DUNE_COMMON_LRU_HH
+
+#include <list>
+#include <utility>
+#include <map>
+
+/** @file
+    @author Christian Engwer
+    @brief LRU Cache Container, using an STL like interface
+
+    Implementatation of an LRU (least recently used) cache
+    container. This implementation follows the approach presented in
+
+    \url
+    http://aim.adc.rmit.edu.au/phd/sgreuter/papers/graphite2003.pdf
+
+ */
+
+namespace Dune {
+
+  template <typename _Key, typename _Tp,
+      typename _Alloc = std::allocator<_Tp> >
+  struct _lru_default_traits
+  {
+    typedef _Key key_type;
+    typedef _Alloc allocator;
+    typedef std::list< std::pair<_Key, _Tp> > list_type;
+    typedef typename list_type::iterator iterator;
+    typedef typename std::less<key_type> cmp;
+    typedef std::map< key_type, iterator, cmp, allocator > map_type;
+  };
+
+  template <typename _Key, typename _Tp,
+      typename _Traits = _lru_default_traits<_Key, _Tp> >
+  class lru
+  {
+    typedef typename _Traits::list_type list_type;
+    typedef typename _Traits::map_type map_type;
+    typedef typename _Traits::allocator allocator;
+    typedef typename map_type::iterator map_iterator;
+    typedef typename map_type::const_iterator const_map_iterator;
+
+  public:
+    typedef typename _Traits::key_type key_type;
+    typedef typename allocator::value_type value_type;
+    typedef typename allocator::pointer pointer;
+    typedef typename allocator::const_pointer const_pointer;
+    typedef typename allocator::const_reference const_reference;
+    typedef typename allocator::reference reference;
+    typedef typename allocator::size_type size_type;
+    typedef typename list_type::iterator iterator;
+    typedef typename list_type::const_iterator const_iterator;
+
+    /**
+     *  Returns a read/write reference to the data of the most
+     *  recently used entry.
+     */
+    reference front()
+    {
+      return _data.front().second;
+    }
+
+    /**
+     *  Returns a read-only (constant) reference to the data of the
+     *  most recently used entry.
+     */
+    const_reference front() const
+    {
+      return _data.front().second;
+    }
+
+    /**
+     *  Returns a read/write reference to the data of the least
+     *  recently used entry.
+     */
+    reference back()
+    {
+      return _data.back().second;
+    }
+
+    /**
+     *  Returns a read-only (constant) reference to the data of the
+     *  least recently used entry.
+     */
+    const_reference back (int i) const
+    {
+      return _data.back().second;
+    }
+
+
+    /**
+     * @brief Removes the first element.
+     */
+    const void pop_front()
+    {
+      key_type k = _data.front().first;
+      _data.pop_front();
+      _index.erase(k);
+    }
+    /**
+     * @brief Removes the last element.
+     */
+    const void pop_back()
+    {
+      key_type k = _data.back().first;
+      _data.pop_back();
+      _index.erase(k);
+    }
+
+    /**
+     * @brief Finds the element whose key is k.
+     *
+     * @return iterator
+     */
+    iterator find (const key_type & key)
+    {
+      const map_iterator it = _index.find(key);
+      if (it == _index.end()) return _data.end();
+      return it->second;
+    }
+
+    /**
+     * @brief Finds the element whose key is k.
+     *
+     * @return const_iterator
+     */
+    const_iterator find (const key_type & key) const
+    {
+      const map_iterator it = _index.find(key);
+      if (it == _index.end()) return _data.end();
+      return it->second;
+    }
+
+    /**
+     * @brief Insert a value into the container
+     *
+     * Stores value under key and marks it as most recent.
+     *
+     * @param key   associated with data
+     * @param data  to store
+     *
+     * @return reference of stored data
+     */
+    reference insert (const key_type & key, const_reference data)
+    {
+      std::pair<key_type, value_type> x(key, data);
+      /* insert item as mru */
+      iterator it = _data.insert(_data.begin(), x);
+      /* store index */
+      _index[key] = it;
+
+      return it->second;
+    }
+
+    /**
+     * @copydoc touch
+     */
+    reference insert (const key_type & key)
+    {
+      return touch (key);
+    }
+
+    /**
+     * @brief mark data associateed with key as most recent
+     *
+     * @return reference of stored data
+     */
+    reference touch (const key_type & key)
+    {
+      /* query _index for iterator */
+      iterator it = _index[key];
+      /* update _data
+         move it to the front
+       */
+      _data.splice(_data.begin(), _data, it);
+      return it->second;
+    }
+
+  private:
+    list_type _data;
+    map_type _index;
+
+  };
+
+} // namespace Dune
+
+#endif // DUNE_COMMON_LRU_HH
diff --git a/common/test/.gitignore b/common/test/.gitignore
index 2b2410ca92080b9f3e5345a02b96ea80156b1ac0..d9ec82012f909541e2ecf1058c68a3b8f718090b 100644
--- a/common/test/.gitignore
+++ b/common/test/.gitignore
@@ -3,6 +3,7 @@ Makefile.in
 .deps
 .libs
 semantic.cache
+lrutest
 parsetest
 test-stack
 arraylisttest
diff --git a/common/test/Makefile.am b/common/test/Makefile.am
index 1d617d308ab0521b9ebe4cb1bd04eea6da2596d7..937b548e4ea489ce8325f5c20b61379183b1c275 100644
--- a/common/test/Makefile.am
+++ b/common/test/Makefile.am
@@ -4,7 +4,7 @@ TESTPROGS = parsetest test-stack arraylisttest smartpointertest \
 	sllisttest iteratorfacadetest tuplestest fvectortest fmatrixtest \
 	poolallocatortest settest gcdlcdtest streamtest \
 	bigunsignedinttest mpihelpertest singletontest mpicollcomm \
-	utilitytest
+	utilitytest lrutest
 
 # which tests to run
 TESTS = $(TESTPROGS)
@@ -21,6 +21,9 @@ bigunsignedinttest_DEPENDENCIES = $(LOCAL_LIBS)
 parsetest_SOURCES = parsetest.cc
 parsetest_DEPENDENCIES = $(LOCAL_LIBS)
 
+lrutest_SOURCES = lrutest.cc
+lrutest_DEPENDENCIES = $(LOCAL_LIBS)
+
 sllisttest_SOURCES = sllisttest.cc
 sllisttest_DEPENDENCIES = $(LOCAL_LIBS)
 
diff --git a/common/test/lrutest.cc b/common/test/lrutest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a4ef1b50e07788dd7c1f3a3b0da2cd301ec67612
--- /dev/null
+++ b/common/test/lrutest.cc
@@ -0,0 +1,42 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#include <assert.h>
+#include <iostream>
+#include <dune/common/lru.hh>
+
+void lru_test()
+{
+  std::cout << "testing Dune::lru<int,double>\n";
+
+  Dune::lru<int, double> lru;
+  lru.insert(10, 1.0);
+  assert(lru.front() == lru.back());
+  lru.insert(11, 2.0);
+  assert(lru.front() == 2.0 && lru.back() == 1.0);
+  lru.insert(12, 99);
+  lru.insert(13, 1.3);
+  lru.insert(14, 12345);
+  lru.insert(15, -17);
+  assert(lru.front() == -17 && lru.back() == 1.0);
+  // update
+  lru.insert(10);
+  assert(lru.front() == 1.0 && lru.back() == 2.0);
+  // update
+  lru.touch(13);
+  assert(lru.front() == 1.3 && lru.back() == 2.0);
+  // remove item
+  lru.pop_front();
+  assert(lru.front() == 1.0 && lru.back() == 2.0);
+  // remove item
+  lru.pop_back();
+  assert(lru.front() == 1.0 && lru.back() == 99);
+
+  std::cout << "... passed\n";
+}
+
+int main ()
+{
+  lru_test();
+
+  return 0;
+}