0

Hi I have about 10 million values and getting Enumeration in enhanced-for loop, but It blasts my RAM. Is there any way to get Iteration rather than Enumeration.

I am trying to to find an alternate for Collections.list() and Collections.enumeration().

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
AZ_
  • 21,688
  • 25
  • 143
  • 191
  • 1
    EnumeratIMHO ion was replaced by Iterator in Java 1.2 (1998) Is there a good reason to still be using it? The simplest solution is not to use the enhanced for loop. Just use a regular loop. – Peter Lawrey Feb 09 '11 at 13:13
  • To make it clear to people just coming to this question: the asker wanted an alternative way to perform a For-Each on an Enumeration, *besides* making a List out of the Enumeration, which would take up extra space. That said, I agree with Peter that you should avoid Enumerations unless you have to use it. – Zach L Feb 09 '11 at 13:14
  • Unfortunately the implementation of Collections.list() is not very smart. While Collections.list() just wraps the collection's iterator by a thin implementation of the Enumeration interface (which needs virtually no time and space) it's a mistery to me why the authors choose to return actually an ArrayList: This decision enforces the implementor to actually allocate RAM large enough to store the complete content of the Enumeration, and then actually copying the content. Using enhanced-for loop for iteration is just like breeze :) – AZ_ Feb 09 '11 at 13:15
  • @Alzaz one benefit of that design is we get a finite sized list. An Enumeration can potentially be constantly growing, so a For-Each on a a constantly growing Enumeration would never stop. If you just want to iterate over the elements 'at the moment,' having a finite-sized list will provide that. However, working around Enumerations just to get a For-Each loop doesn't seem worth it – Zach L Feb 09 '11 at 13:17
  • This is a work around for iteration over an Infinite list. Imagine it with the Collections.list or Collections.enumeration what will happen with you RAM. Well sometimes you get into situations where things becomes necessary. – AZ_ Feb 09 '11 at 13:23
  • It is something like endless list scroller in Android. Where you have to put N number of items into list for user to view. I hope you got my point. – AZ_ Feb 09 '11 at 13:26
  • @Peter Lawrey: I am trying to get Iteration for Enumeration. – AZ_ Feb 09 '11 at 13:29
  • Its still not clear why you are using an Enumeration, what is the underlying class you enumerating and do you access to it? – Peter Lawrey Feb 09 '11 at 13:45
  • @Alzaz why do you NEED iteration over an enumeration? What can't you just use a regular for loop like `for (Enumeration enumeration = getEnumeration(); enumeration.hasMoreElements();)` ? Yes, it's not as elegant as iteration, but it's not that bad either. – Zach L Feb 09 '11 at 13:48
  • BTW: A List with 10 million elements should only use 40 MB of memory. What sort of device are you programming for? – Peter Lawrey Feb 09 '11 at 13:49

2 Answers2

1
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
public final class Enumerations {

    /**
     * Allows using of {@link Enumeration} with the for-each statement. The
     * implementation is not using any heap space and such is able to serve
     * virtually endless Enumerations, while {@link Collections#list} is limited
     * by available RAM. As a result, this implementation is much faster than
     * Collections.list.
     * 
     * @param enumeration
     *            The original enumeration.
     * @return An {@link Iterable} directly calling the original Enumeration.
     */
    public static final <T> Iterable<T> iterable(final Enumeration<T> enumeration) {
        return new Iterable<T>() {
            public final Iterator<T> iterator() {
                return new Iterator<T>() {
                    public final boolean hasNext() {
                        return enumeration.hasMoreElements();
                    }

                    public final T next() {
                        return enumeration.nextElement();
                    }

                    /**
                     * This method is not implemeted as it is impossible to
                     * remove something from an Enumeration.
                     * 
                     * @throws UnsupportedOperationException
                     *             always.
                     */
                    public final void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

}
AZ_
  • 21,688
  • 25
  • 143
  • 191
  • This has the "cosmetic" error that it works only once, i.e. if you want to get only one Iterator from your Iterable. This is fine for the enhanced for loop, but violates the general contract of Iterable, I think. This may be the reason the `list()` method creates a new List instead of doing it like you did here. – Paŭlo Ebermann Feb 09 '11 at 14:11
  • 1
    The contract of Iterable is very loose. It only guarantees that the iterator returns elements of the correct type. It says nothing about what elements that iterator returns. – ILMTitan Feb 09 '11 at 19:54
0

A trick I use quite often which may help is say you have a method which takes a collection.

 populate(List<String> list);

and you don't want to change the method but you know it only uses the add() method. You can do the following

 List<String> list = new ArraysList<String>() {
    public boolean add(String text) {
        myProcess(text);
        return false;
    }
 };
 populate(List<String> list);

In this case, populate can add any amount of data without using additional memory.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130