ACMNexus / google-collections

Automatically exported from code.google.com/p/google-collections
Apache License 2.0
0 stars 0 forks source link

array based iteration for maps #65

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
Utility method I use, maybe you guys find it useful.

  /**
   * Get an {@link Iterable} for the given map that returns an {@link Iterator}
   * that returns its entries as a two element array. Only works for maps where
   * the types of the key and the value are the same.
   * <p>
   * The {@link Iterator} returned by the {@link Iterable} does not support 
   * the {@link Iterator#remove()} operation, and will throw
   * {@link UnsupportedOperationException} when invoked.
   * <p>
   * Caution: the returned {@link Iterable} performs at least three times worse
   *          than regular EntrySet iteration (http://tinyurl.com/5zgejx)
   * 
   * @param  <T> type of the specified map's keys as well as values
   * @param  map the map for which to get an array based iterator
   * @return an {@link Iterable} that gives out {@link Iterator}s that return
   *         map entries as a two-element array with the key in the first 
   *         position (zero) and the value in the second position (one)
   * @throws NullPointerException if the given map contains a <code>null</code>
   *         key
   */
  public static <T> Iterable<T[]> arrayIterable(final Map<T,T> map) {
    // containsKey can also throw NullPointerException but that's what
    // we want anyway
    if (map.containsKey(null)) throw new NullPointerException();

    return new Iterable<T[]>() {
      public Iterator<T[]> iterator() {
        return new Iterator<T[]>() {
          // backing iterator
          private final Iterator<Entry<T,T>> iter = map.entrySet().iterator();
          // two-element array representing map entries
          // created once and then reused
          private T[] array;

          public boolean hasNext() { 
            return iter.hasNext(); 
          }
          public T[] next() {
            return toArray(iter.next());
          }
          public void remove() {
            throw new UnsupportedOperationException();
          }

          @SuppressWarnings("unchecked")
          private T[] toArray(Entry<T,T> e) {
            if (array == null)
              array = (T[]) Array.newInstance(e.getKey().getClass(), 2);
            array[0] = e.getKey(); array[1] = e.getValue();
            return array;
          }
        };
      }
    };
  }

Original issue reported on code.google.com by robbie.v...@gmail.com on 12 May 2008 at 12:11

GoogleCodeExporter commented 8 years ago
Thanks for suggesting this.

However, I don't see the advantage of this over the standard Map.entrySet() 
iterator.

Original comment by jared.l....@gmail.com on 12 May 2008 at 12:59

GoogleCodeExporter commented 8 years ago
The advantage is in the syntax:
for (String[] s : arrayIterable(map))
    System.out.println(s[0] +" "+ s[1]);

versus

for (Map.Entry<String, String> s : map.entrySet())
    System.out.println(s.getKey + " " + s.getValue());

Original comment by robbie.v...@gmail.com on 12 May 2008 at 9:37

GoogleCodeExporter commented 8 years ago
@Robbie
This may be of interest:
http://docs.google.com/View?docid=dfn5297z_14dwzrkpgw

Original comment by gk5...@gmail.com on 12 May 2008 at 3:05