Java tutorial
import java.io.Serializable; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; // // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* ------------------------------------------------------------ */ /** A multi valued Map. * This Map specializes HashMap and provides methods * that operate on multi valued items. * <P> * Implemented as a map of LazyList values * * @see LazyList * @author Greg Wilkins (gregw) */ public class MultiMap extends HashMap implements Cloneable { /* ------------------------------------------------------------ */ /** Constructor. */ public MultiMap() { } /* ------------------------------------------------------------ */ /** Constructor. * @param size Capacity of the map */ public MultiMap(int size) { super(size); } /* ------------------------------------------------------------ */ /** Constructor. * @param map */ public MultiMap(Map map) { super((map.size() * 3) / 2); putAll(map); } /* ------------------------------------------------------------ */ /** Get multiple values. * Single valued entries are converted to singleton lists. * @param name The entry key. * @return Unmodifieable List of values. */ public List getValues(Object name) { return LazyList.getList(super.get(name), true); } /* ------------------------------------------------------------ */ /** Get a value from a multiple value. * If the value is not a multivalue, then index 0 retrieves the * value or null. * @param name The entry key. * @param i Index of element to get. * @return Unmodifieable List of values. */ public Object getValue(Object name, int i) { Object l = super.get(name); if (i == 0 && LazyList.size(l) == 0) return null; return LazyList.get(l, i); } /* ------------------------------------------------------------ */ /** Get value as String. * Single valued items are converted to a String with the toString() * Object method. Multi valued entries are converted to a comma separated * List. No quoting of commas within values is performed. * @param name The entry key. * @return String value. */ public String getString(Object name) { Object l = super.get(name); switch (LazyList.size(l)) { case 0: return null; case 1: Object o = LazyList.get(l, 0); return o == null ? null : o.toString(); default: StringBuffer values = new StringBuffer(128); synchronized (values) { for (int i = 0; i < LazyList.size(l); i++) { Object e = LazyList.get(l, i); if (e != null) { if (values.length() > 0) values.append(','); values.append(e.toString()); } } return values.toString(); } } } /* ------------------------------------------------------------ */ public Object get(Object name) { Object l = super.get(name); switch (LazyList.size(l)) { case 0: return null; case 1: Object o = LazyList.get(l, 0); return o; default: return LazyList.getList(l, true); } } /* ------------------------------------------------------------ */ /** Put and entry into the map. * @param name The entry key. * @param value The entry value. * @return The previous value or null. */ public Object put(Object name, Object value) { return super.put(name, LazyList.add(null, value)); } /* ------------------------------------------------------------ */ /** Put multi valued entry. * @param name The entry key. * @param values The List of multiple values. * @return The previous value or null. */ public Object putValues(Object name, List values) { return super.put(name, values); } /* ------------------------------------------------------------ */ /** Put multi valued entry. * @param name The entry key. * @param values The String array of multiple values. * @return The previous value or null. */ public Object putValues(Object name, String[] values) { Object list = null; for (int i = 0; i < values.length; i++) list = LazyList.add(list, values[i]); return put(name, list); } /* ------------------------------------------------------------ */ /** Add value to multi valued entry. * If the entry is single valued, it is converted to the first * value of a multi valued entry. * @param name The entry key. * @param value The entry value. */ public void add(Object name, Object value) { Object lo = super.get(name); Object ln = LazyList.add(lo, value); if (lo != ln) super.put(name, ln); } /* ------------------------------------------------------------ */ /** Add values to multi valued entry. * If the entry is single valued, it is converted to the first * value of a multi valued entry. * @param name The entry key. * @param values The List of multiple values. */ public void addValues(Object name, List values) { Object lo = super.get(name); Object ln = LazyList.addCollection(lo, values); if (lo != ln) super.put(name, ln); } /* ------------------------------------------------------------ */ /** Add values to multi valued entry. * If the entry is single valued, it is converted to the first * value of a multi valued entry. * @param name The entry key. * @param values The String array of multiple values. */ public void addValues(Object name, String[] values) { Object lo = super.get(name); Object ln = LazyList.addCollection(lo, Arrays.asList(values)); if (lo != ln) super.put(name, ln); } /* ------------------------------------------------------------ */ /** Remove value. * @param name The entry key. * @param value The entry value. * @return true if it was removed. */ public boolean removeValue(Object name, Object value) { Object lo = super.get(name); Object ln = lo; int s = LazyList.size(lo); if (s > 0) { ln = LazyList.remove(lo, value); if (ln == null) super.remove(name); else super.put(name, ln); } return LazyList.size(ln) != s; } /* ------------------------------------------------------------ */ /** Put all contents of map. * @param m Map */ public void putAll(Map m) { Iterator i = m.entrySet().iterator(); boolean multi = m instanceof MultiMap; while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); if (multi) super.put(entry.getKey(), LazyList.clone(entry.getValue())); else put(entry.getKey(), entry.getValue()); } } /* ------------------------------------------------------------ */ /** * @return Map of String arrays */ public Map toStringArrayMap() { HashMap map = new HashMap(size() * 3 / 2); Iterator i = super.entrySet().iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); Object l = entry.getValue(); String[] a = LazyList.toStringArray(l); // for (int j=a.length;j-->0;) // if (a[j]==null) // a[j]=""; map.put(entry.getKey(), a); } return map; } /* ------------------------------------------------------------ */ public Object clone() { MultiMap mm = (MultiMap) super.clone(); Iterator iter = mm.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); entry.setValue(LazyList.clone(entry.getValue())); } return mm; } } // //Copyright 2004-2005 Mort Bay Consulting Pty. Ltd. //------------------------------------------------------------------------ //Licensed under the Apache License, Version 2.0 (the "License"); //you may not use this file except in compliance with the License. //You may obtain a copy of the License at //http://www.apache.org/licenses/LICENSE-2.0 //Unless required by applicable law or agreed to in writing, software //distributed under the License is distributed on an "AS IS" BASIS, //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //See the License for the specific language governing permissions and //limitations under the License. // /* ------------------------------------------------------------ */ /** Lazy List creation. * A List helper class that attempts to avoid unneccessary List * creation. If a method needs to create a List to return, but it is * expected that this will either be empty or frequently contain a * single item, then using LazyList will avoid additional object * creations by using Collections.EMPTY_LIST or * Collections.singletonList where possible. * * <p><h4>Usage</h4> * <pre> * Object lazylist =null; * while(loopCondition) * { * Object item = getItem(); * if (item.isToBeAdded()) * lazylist = LazyList.add(lazylist,item); * } * return LazyList.getList(lazylist); * </pre> * * An ArrayList of default size is used as the initial LazyList. * * @see java.util.List * @author Greg Wilkins (gregw) */ class LazyList implements Cloneable, Serializable { private static final String[] __EMTPY_STRING_ARRAY = new String[0]; /* ------------------------------------------------------------ */ private LazyList() { } /* ------------------------------------------------------------ */ /** Add an item to a LazyList * @param list The list to add to or null if none yet created. * @param item The item to add. * @return The lazylist created or added to. */ public static Object add(Object list, Object item) { if (list == null) { if (item instanceof List || item == null) { List l = new ArrayList(); l.add(item); return l; } return item; } if (list instanceof List) { ((List) list).add(item); return list; } List l = new ArrayList(); l.add(list); l.add(item); return l; } /* ------------------------------------------------------------ */ /** Add an item to a LazyList * @param list The list to add to or null if none yet created. * @param index The index to add the item at. * @param item The item to add. * @return The lazylist created or added to. */ public static Object add(Object list, int index, Object item) { if (list == null) { if (index > 0 || item instanceof List || item == null) { List l = new ArrayList(); l.add(index, item); return l; } return item; } if (list instanceof List) { ((List) list).add(index, item); return list; } List l = new ArrayList(); l.add(list); l.add(index, item); return l; } /* ------------------------------------------------------------ */ /** Add the contents of a Collection to a LazyList * @param list The list to add to or null if none yet created. * @param collection The Collection whose contents should be added. * @return The lazylist created or added to. */ public static Object addCollection(Object list, Collection collection) { Iterator i = collection.iterator(); while (i.hasNext()) list = LazyList.add(list, i.next()); return list; } /* ------------------------------------------------------------ */ /** Add the contents of an array to a LazyList * @param list The list to add to or null if none yet created. * @param collection The Collection whose contents should be added. * @return The lazylist created or added to. */ public static Object addArray(Object list, Object[] array) { for (int i = 0; array != null && i < array.length; i++) list = LazyList.add(list, array[i]); return list; } /* ------------------------------------------------------------ */ /** Ensure the capcity of the underlying list. * */ public static Object ensureSize(Object list, int initialSize) { if (list == null) return new ArrayList(initialSize); if (list instanceof ArrayList) { ArrayList ol = (ArrayList) list; if (ol.size() > initialSize) return ol; ArrayList nl = new ArrayList(initialSize); nl.addAll(ol); return nl; } List l = new ArrayList(initialSize); l.add(list); return l; } /* ------------------------------------------------------------ */ public static Object remove(Object list, Object o) { if (list == null) return null; if (list instanceof List) { List l = (List) list; l.remove(o); if (l.size() == 0) return null; return list; } if (list.equals(o)) return null; return list; } /* ------------------------------------------------------------ */ public static Object remove(Object list, int i) { if (list == null) return null; if (list instanceof List) { List l = (List) list; l.remove(i); if (l.size() == 0) return null; return list; } if (i == 0) return null; return list; } /* ------------------------------------------------------------ */ /** Get the real List from a LazyList. * * @param list A LazyList returned from LazyList.add(Object) * @return The List of added items, which may be an EMPTY_LIST * or a SingletonList. */ public static List getList(Object list) { return getList(list, false); } /* ------------------------------------------------------------ */ /** Get the real List from a LazyList. * * @param list A LazyList returned from LazyList.add(Object) or null * @param nullForEmpty If true, null is returned instead of an * empty list. * @return The List of added items, which may be null, an EMPTY_LIST * or a SingletonList. */ public static List getList(Object list, boolean nullForEmpty) { if (list == null) return nullForEmpty ? null : Collections.EMPTY_LIST; if (list instanceof List) return (List) list; List l = new ArrayList(1); l.add(list); return l; } /* ------------------------------------------------------------ */ public static String[] toStringArray(Object list) { if (list == null) return __EMTPY_STRING_ARRAY; if (list instanceof List) { List l = (List) list; String[] a = new String[l.size()]; for (int i = l.size(); i-- > 0;) { Object o = l.get(i); if (o != null) a[i] = o.toString(); } return a; } return new String[] { list.toString() }; } /* ------------------------------------------------------------ */ public static Object toArray(Object list, Class aClass) { if (list == null) return (Object[]) Array.newInstance(aClass, 0); if (list instanceof List) { List l = (List) list; if (aClass.isPrimitive()) { Object a = Array.newInstance(aClass, l.size()); for (int i = 0; i < l.size(); i++) Array.set(a, i, l.get(i)); return a; } return l.toArray((Object[]) Array.newInstance(aClass, l.size())); } Object a = Array.newInstance(aClass, 1); Array.set(a, 0, list); return a; } /* ------------------------------------------------------------ */ /** The size of a lazy List * @param list A LazyList returned from LazyList.add(Object) or null * @return the size of the list. */ public static int size(Object list) { if (list == null) return 0; if (list instanceof List) return ((List) list).size(); return 1; } /* ------------------------------------------------------------ */ /** Get item from the list * @param list A LazyList returned from LazyList.add(Object) or null * @param i int index * @return the item from the list. */ public static Object get(Object list, int i) { if (list == null) throw new IndexOutOfBoundsException(); if (list instanceof List) return ((List) list).get(i); if (i == 0) return list; throw new IndexOutOfBoundsException(); } /* ------------------------------------------------------------ */ public static boolean contains(Object list, Object item) { if (list == null) return false; if (list instanceof List) return ((List) list).contains(item); return list.equals(item); } /* ------------------------------------------------------------ */ public static Object clone(Object list) { if (list == null) return null; if (list instanceof List) return new ArrayList((List) list); return list; } /* ------------------------------------------------------------ */ public static String toString(Object list) { if (list == null) return "[]"; if (list instanceof List) return ((List) list).toString(); return "[" + list + "]"; } /* ------------------------------------------------------------ */ public static Iterator iterator(Object list) { if (list == null) return Collections.EMPTY_LIST.iterator(); if (list instanceof List) return ((List) list).iterator(); return getList(list).iterator(); } /* ------------------------------------------------------------ */ public static ListIterator listIterator(Object list) { if (list == null) return Collections.EMPTY_LIST.listIterator(); if (list instanceof List) return ((List) list).listIterator(); return getList(list).listIterator(); } /* ------------------------------------------------------------ */ /** * @param array Any array of object * @return A new <i>modifiable</i> list initialised with the elements from <code>array</code>. */ public static List array2List(Object[] array) { if (array == null || array.length == 0) return new ArrayList(); return new ArrayList(Arrays.asList(array)); } /* ------------------------------------------------------------ */ /** Add element to an array * @param array The array to add to (or null) * @param item The item to add * @param type The type of the array (in case of null array) * @return new array with contents of array plus item */ public static Object[] addToArray(Object[] array, Object item, Class type) { if (array == null) { if (type == null && item != null) type = item.getClass(); Object[] na = (Object[]) Array.newInstance(type, 1); na[0] = item; return na; } else { Class c = array.getClass().getComponentType(); Object[] na = (Object[]) Array.newInstance(c, Array.getLength(array) + 1); System.arraycopy(array, 0, na, 0, array.length); na[array.length] = item; return na; } } /* ------------------------------------------------------------ */ public static Object[] removeFromArray(Object[] array, Object item) { if (item == null || array == null) return array; for (int i = array.length; i-- > 0;) { if (item.equals(array[i])) { Class c = array == null ? item.getClass() : array.getClass().getComponentType(); Object[] na = (Object[]) Array.newInstance(c, Array.getLength(array) - 1); if (i > 0) System.arraycopy(array, 0, na, 0, i); if (i + 1 < array.length) System.arraycopy(array, i + 1, na, i, array.length - (i + 1)); return na; } } return array; } }