/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.collections; import java.util.AbstractList; import java.util.List; import xxl.core.functions.Function; /** * The class provides a mapping of a list with a given function. The list to * map and the mapping function are internally stored and the indexed access * methods <code>get</code> and <code>remove</code> are implemented. Every * method that adds or sets elements throws an UnsupportedOperationException * (the element to insert cannot be <i>back-mapped</i>). Everytime one of the * implemented methods is called on this list the mapping function is invoked * with the corresponding element of the internally used list. The iterators * returned by the <code>iterator</code> and <code>listIterator</code> methods * are also mapped. * * <p>The performance of the mapped list depends on the internally stored list * that is specified when the mapped list is constructed.</p> * * <p>Usage example (1). * <code><pre> * // create a new list * * List<Integer> list = new ArrayList<Integer>(); * * // insert the Integers between 0 and 19 into the list * * for (int i = 0; i < 20; i++) * list.add(i); * * // create a function that multplies every odd Integer with 10 and divides every even * // Integer by 2 * * Function<Integer, Integer> function = new Function<Integer, Iteger>() { * public Integer invoke(Integer o) { * return o%2 != 0 ? o*10 : o/2; * } * }; * * // create a new mapped list that maps the given list with the given function * * MappedList<Integer, Integer> mappedList = new MappedList<Integer, Integer>(list, function); * * // print all elements of the mapped list * * for (int i = 0; i < mappedList.size(); i++) * System.out.println(mappedList.get(i)); * </pre></code></p> * * @param <I> the type of the elements stored by the underlying list. * @param <O> the type of the elements returned by the methods of this list. * @see AbstractList * @see Function * @see List */ public class MappedList<I, O> extends AbstractList<O> { /** * This field is used to store the list to map internally. */ protected List<? extends I> list; /** * This field is used to store the mapping function. */ protected Function<? super I, ? extends O> function; /** * Constructs a new mapped list that maps the specified list with the * specified function. * * @param list the list to map. * @param function the mapping function. */ public MappedList(List<? extends I> list, Function<? super I, ? extends O> function) { this.list = list; this.function = function; } /** * This implementation always throws an UnsupportedOperationException. * * @param element element to be inserted. * @return * @throws UnsupportedOperationException if the <tt>add</tt> method is not * supported by this list. * @throws ClassCastException if the class of the specified element * prevents it from being added to this list. * @throws IllegalArgumentException if some aspect of the specified * element prevents it from being added to this list. * @throws IndexOutOfBoundsException index is out of range (<tt>index < * 0 || index > size()</tt>). */ // @Override public boolean add(O element) { throw new UnsupportedOperationException("element " + element + " cannot be added to a mapped list."); } public void add(int index, O element) { throw new UnsupportedOperationException("element " + element + " cannot be added to a mapped list."); }; /** * Returns the number of elements in this list. * * @return the number of elements in this list. */ public int size() { return list.size(); } /** * Returns the mapped element at the specified position in this list. This * method is equivalent to the call of * <code>function.invoke(list.get(index))</code>. * * @param index index of element to return. * @return the mapped element at the specified position in this list. * @throws UnsupportedOperationException if the remove method is not * supported by this list. */ public O get(int index) throws UnsupportedOperationException { return function.invoke(list.get(index)); } /** * Removes the element at the specified position in this list. Shifts any * subsequent elements to the left (subtracts one from their indices). * Returns the element that was removed from the list. This method is * equivalent to the call of * <code>function.invoke(list.remove(index))</code>. * * @param index the index of the element to remove. * @return the mapped element previously at the specified position. * @throws IndexOutOfBoundsException if the <code>index</code> is out of * range (<code>index < 0 || index >= size()</code>). */ public O remove (int index) throws IndexOutOfBoundsException { return function.invoke(list.remove(index)); } }