diff --git a/product/ERP5Type/Core/Folder.py b/product/ERP5Type/Core/Folder.py
index 1ee3a5130e54e8d229d93acf23382ceb34c07176..21c7d36142595845b8cd17571ff5c644c1d6ceb4 100644
--- a/product/ERP5Type/Core/Folder.py
+++ b/product/ERP5Type/Core/Folder.py
@@ -914,6 +914,7 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
     if self._folder_handler == HBTREE_HANDLER:
       if self._htree is None:
         return []
+      assert spec is None
       if kw.has_key("base_id"):
         return CMFHBTreeFolder.objectIds(self, base_id=kw["base_id"])
       else:
@@ -927,6 +928,7 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
     if self._folder_handler == HBTREE_HANDLER:
       if  self._htree is None:
         return []
+      assert spec is None
       if kw.has_key("base_id"):
         return CMFHBTreeFolder.objectItems(self, base_id=kw["base_id"])
       else:
@@ -936,16 +938,6 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
         return []
       return CMFBTreeFolder.objectItems(self, spec)
 
-  def objectMap(self):
-    if self._folder_handler == HBTREE_HANDLER:
-      if self._htree is None:
-        return []
-      return CMFHBTreeFolder.objectMap(self)
-    else:
-      if self._tree is None:
-        return []
-      return CMFBTreeFolder.objectIMap(self)
-
   def objectIds_d(self, t=None):
     if self._folder_handler == HBTREE_HANDLER:
       if self._htree is None:
@@ -956,16 +948,6 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
         return {}
       return CMFBTreeFolder.objectIds_d(self, t)
 
-  def objectMap_d(self, t=None):
-    if self._folder_handler == HBTREE_HANDLER:
-      if self._htree is None:
-        return {}
-      return CMFHBTreeFolder.objectMap_d(self, t)
-    else:
-      if self._tree is None:
-        return {}
-      return CMFBTreeFolder.objectMap_d(self, t)
-
   def _checkId(self, id, allow_dup=0):
     if self._folder_handler == HBTREE_HANDLER:
       return CMFHBTreeFolder._checkId(self, id, allow_dup)
@@ -1545,6 +1527,7 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn):
     elif self._folder_handler == HBTREE_HANDLER:
       if self._htree is None:
         return []
+      assert spec is None
       if 'base_id' in kw:
         object_list = CMFHBTreeFolder.objectValues(self, base_id=kw['base_id'])
       else:
diff --git a/product/HBTreeFolder2/HBTreeFolder2.py b/product/HBTreeFolder2/HBTreeFolder2.py
index bcdd4e249e1ccb4fd3bbd37fb15e75f7603e9f81..9edd73417e252b22e98a0d016b4c639cece10a35 100644
--- a/product/HBTreeFolder2/HBTreeFolder2.py
+++ b/product/HBTreeFolder2/HBTreeFolder2.py
@@ -14,6 +14,7 @@
 
 import sys
 from cgi import escape
+from itertools import chain, islice
 from urllib import quote
 from random import randint
 from types import StringType
@@ -32,7 +33,6 @@ from AccessControl import getSecurityManager, ClassSecurityInfo
 from AccessControl.Permissions import access_contents_information, \
      view_management_screens
 from zLOG import LOG, INFO, ERROR, WARNING
-from Products.ZCatalog.Lazy import LazyMap, LazyFilter, LazyCat, LazyValues
 
 
 manage_addHBTreeFolder2Form = DTMLFile('folderAdd', globals())
@@ -67,6 +67,69 @@ class ExhaustedUniqueIdsError (Exception):
     pass
 
 
+class HBTreeObjectIds(object):
+
+    _index = float('inf')
+
+    def __init__(self, tree, base_id=_marker):
+        self._tree = tree
+        if base_id is _marker:
+            tree_id_list = tree.getTreeIdList()
+            self._count = tree._count
+        else:
+            tree_id_list = base_id,
+        check = tree._checkObjectId
+        self._keys = lambda: (x for base_id in tree_id_list
+                                for x in (tree._htree if base_id is None else
+                                          tree._getTree(base_id)).keys()
+                                if check((base_id, x)))
+
+    def _count(self):
+        count = sum(1 for x in self._keys())
+        self._count = lambda: count
+        return count
+
+    def __len__(self):
+        return self._count()
+
+    def __iter__(self):
+        return self._keys()
+
+    def __getitem__(self, item):
+        if item < 0:
+            item += self._count()
+        i = self._index
+        self._index = item + 1
+        i = item - i
+        try:
+            if i < 0:
+                self._ikeys = keys = self._keys()
+                return islice(keys, item, None).next()
+            return (islice(self._ikeys, i, None) if i else self._ikeys).next()
+        except StopIteration:
+            del self._index, self._ikeys
+            raise IndexError
+
+class HBTreeObjectItems(HBTreeObjectIds):
+
+    def __iter__(self):
+        getOb = self._tree._getOb
+        return ((x, getOb(x)) for x in self._keys())
+
+    def __getitem__(self, item):
+        object_id = HBTreeObjectIds.__getitem__(self, item)
+        return object_id, self._tree._getOb(object_id)
+
+class HBTreeObjectValues(HBTreeObjectIds):
+
+    def __iter__(self):
+        getOb = self._tree._getOb
+        return (getOb(x) for x in self._keys())
+
+    def __getitem__(self, item):
+        return self._tree._getOb(HBTreeObjectIds.__getitem__(self, item))
+
+
 class HBTreeFolder2Base (Persistent):
     """Base for BTree-based folders.
     """
@@ -198,6 +261,7 @@ class HBTreeFolder2Base (Persistent):
     def hashId(self, id):
         """Return a tuple of ids
         """
+        # XXX: why tolerate non-string ids ?
         id_list = str(id).split(H_SEPARATOR)     # We use '-' as the separator by default
         if len(id_list) > 1:
           return tuple(id_list)
@@ -288,7 +352,6 @@ class HBTreeFolder2Base (Persistent):
         b_count = int(REQUEST.get('b_count', 1000))
         b_end = b_start + b_count - 1
         url = self.absolute_url() + '/manage_main'
-        idlist = self.objectIds()  # Pre-sorted.
         count = self.objectCount()
 
         if b_end < count:
@@ -302,10 +365,9 @@ class HBTreeFolder2Base (Persistent):
         else:
             prev_url = ''
 
-        formatted = []
-        formatted.append(listtext0 % pref_rows)
-        for i in range(b_start - 1, b_end):
-            optID = escape(idlist[i])
+        formatted = [listtext0 % pref_rows]
+        for optID in islice(self.objectIds(), b_start - 1, b_end):
+            optID = escape(optID)
             formatted.append(listtext1 % (escape(optID, quote=1), optID))
         formatted.append(listtext2)
         return {'b_start': b_start, 'b_end': b_end,
@@ -404,7 +466,7 @@ class HBTreeFolder2Base (Persistent):
         """ Return a list of subtree ids
         """
         tree = self._getTree(base_id=base_id)
-        return [x for x in self._htree.keys() if isinstance(self._htree[x], OOBTree)]
+        return [k for k, v in self._htree.items() if isinstance(v, OOBTree)]
 
 
     def _getTree(self, base_id):
@@ -448,31 +510,6 @@ class HBTreeFolder2Base (Persistent):
                 self._tree_list[tree] = None
         return sorted(self._tree_list.keys())
 
-
-    def _treeObjectValues(self, base_id=None):
-        """ return object values for a given btree
-        """
-        if base_id is not None:
-            return LazyFilter(self._isNotBTree, self._getTree("%s" %base_id).values())
-        else:
-            return LazyFilter(self._isNotBTree, self._htree.values())
-
-    def _treeObjectIds(self, base_id=None):
-        """ return object ids for a given btree
-        """
-        if base_id is not None:
-          return LazyValues(LazyFilter(self._checkObjectId, [(base_id, x) for x in self._getTree("%s" %base_id).keys()]))
-        else:
-          return LazyValues(LazyFilter(self._checkObjectId, [(base_id, x) for x in self._htree.keys()]))
-
-    def _isNotBTree(self, obj):
-        """ test object is not a btree
-        """
-        if isinstance(obj, OOBTree):
-            return False
-        else:
-            return True
-
     def _checkObjectId(self, ids):
         """ test id is not in btree id list
         """
@@ -483,36 +520,21 @@ class HBTreeFolder2Base (Persistent):
         
     security.declareProtected(access_contents_information,
                               'objectValues')
-    def objectValues(self, base_id=_marker, spec=None):
-        return LazyMap(self._getOb, self.objectIds(base_id=base_id))
-
+    def objectValues(self, base_id=_marker):
+        return HBTreeObjectValues(self, base_id)
 
     security.declareProtected(access_contents_information,
                               'objectIds')
-    def objectIds(self, base_id=_marker, spec=None):
-        if base_id is _marker:
-            return LazyCat(LazyMap(self._treeObjectIds, self.getTreeIdList()))
-        else:
-            return self._treeObjectIds(base_id=base_id)
+    def objectIds(self, base_id=_marker):
+        return HBTreeObjectIds(self, base_id)
 
-    
     security.declareProtected(access_contents_information,
                               'objectItems')
-    def objectItems(self, base_id=_marker, spec=None):
+    def objectItems(self, base_id=_marker):
         # Returns a list of (id, subobject) tuples of the current object.
         # If 'spec' is specified, returns only objects whose meta_type match
         # 'spec'
-        return LazyMap(lambda id, _getOb=self._getOb: (id, _getOb(id)),
-                       self.objectIds(base_id=base_id))
-
-
-    security.declareProtected(access_contents_information,
-                              'objectMap')
-    def objectMap(self):
-        # Returns a tuple of mappings containing subobject meta-data.
-        return LazyMap(lambda (k, v):
-                       {'id': k, 'meta_type': getattr(v, 'meta_type', None)},
-                       self._htree.items(), self._count())
+        return HBTreeObjectItems(self, base_id)
 
     # superValues() looks for the _objects attribute, but the implementation
     # would be inefficient, so superValues() support is disabled.
@@ -522,18 +544,7 @@ class HBTreeFolder2Base (Persistent):
     security.declareProtected(access_contents_information,
                               'objectIds_d')
     def objectIds_d(self, t=None):
-        ids = self.objectIds(t)
-        res = {}
-        for id in ids:
-            res[id] = 1
-        return res
-
-
-    security.declareProtected(access_contents_information,
-                              'objectMap_d')
-    def objectMap_d(self, t=None):
-        return self.objectMap()
-
+        return dict.fromkeys(self.objectIds(t), 1)
 
     def _checkId(self, id, allow_dup=0):
         if not allow_dup and self.has_key(id):
diff --git a/product/HBTreeFolder2/tests/testHBTreeFolder2.py b/product/HBTreeFolder2/tests/testHBTreeFolder2.py
index 1bf25a55633086205566fc3e778480b250b71c94..78eb7383a6a1a5ad3d93d82c85bd9d9f5799c072 100644
--- a/product/HBTreeFolder2/tests/testHBTreeFolder2.py
+++ b/product/HBTreeFolder2/tests/testHBTreeFolder2.py
@@ -84,14 +84,6 @@ class HBTreeFolder2Tests(ERP5TypeTestCase):
         self.assertEqual(list(self.f.objectIds()), [])
         self.assertEqual(self.f.objectCount(), 0)
 
-    def testObjectMap(self):
-        map = self.f.objectMap()
-        self.assertEqual(list(map), [{'id': 'item', 'meta_type':
-                                      self.ff.meta_type}])
-        # I'm not sure why objectMap_d() exists, since it appears to be
-        # the same as objectMap(), but it's implemented by Folder.
-        self.assertEqual(list(self.f.objectMap_d()), list(self.f.objectMap()))
-
     def testObjectIds_d(self):
         self.assertEqual(self.f.objectIds_d(), {'item': 1})
 
@@ -145,7 +137,7 @@ class HBTreeFolder2Tests(ERP5TypeTestCase):
         f2 = HBTreeFolder2('somefolder')
         self.f._setObject(f2.id, f2)
         # Hack in an absolute_url() method that works without context.
-        self.f.absolute_url = lambda: ''
+        self.f.absolute_url = str
         info = self.f.getBatchObjectListing()
         self.assertEqual(info['b_start'], 1)
         self.assertEqual(info['b_end'], 2)
@@ -177,7 +169,7 @@ class HBTreeFolder2Tests(ERP5TypeTestCase):
         name = " some folder "
         f2 = HBTreeFolder2(name)
         self.f._setObject(f2.id, f2)
-        self.f.absolute_url = lambda: ''
+        self.f.absolute_url = str
         info = self.f.getBatchObjectListing()
         expect = '<option value="%s">%s</option>' % (name, name)
         self.assert_(info['formatted_list'].find(expect) > 0)
@@ -231,7 +223,7 @@ class HBTreeFolder2Tests(ERP5TypeTestCase):
           h._delOb(i)
 
     @expectedFailure
-    def testPerformanceInDepth(self):
+    def _testPerformanceInDepth(self):
         """
         Check HBTreeFolder2 GET performance with the depth and the number of
         documents.