001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.internal;
018
019import static org.apache.juneau.internal.ArrayUtils.*;
020
021import java.lang.reflect.*;
022import java.util.*;
023
024import org.apache.juneau.common.utils.*;
025
026/**
027 * An instance of a <c>Map</c> where the keys and values are simple arrays.
028 *
029 * <p>
030 * Typically more efficient than <c>HashMaps</c> for small maps (e.g. &lt;10 entries).
031 *
032 * <p>
033 * Does not support adding or removing entries.
034 *
035 * <p>
036 * Setting values overwrites the value on the underlying value array.
037 *
038 * <h5 class='section'>See Also:</h5><ul>
039
040 * </ul>
041 *
042 * @param <K> The key type.
043 * @param <V> The value type.
044 */
045public class SimpleMap<K,V> extends AbstractMap<K,V> {
046
047   final K[] keys;
048   final V[] values;
049   final SimpleMapEntry[] entries;
050
051   /**
052    * Constructor.
053    *
054    * @param keys The map keys.  Must not be <jk>null</jk>.
055    * @param values The map values.  Must not be <jk>null</jk>.
056    */
057   @SuppressWarnings("unchecked")
058   public SimpleMap(K[] keys, V[] values) {
059      Utils.assertArgNotNull("keys", keys);
060      Utils.assertArgNotNull("values", values);
061      Utils.assertArg(keys.length == values.length, "keys ''{0}'' and values ''{1}'' array lengths differ", keys.length, values.length);
062
063      this.keys = keys;
064      this.values = values;
065      entries = (SimpleMapEntry[]) Array.newInstance(SimpleMapEntry.class, keys.length);
066      for (int i = 0; i < keys.length; i++) {
067         Utils.assertArg(keys[i] != null, "Keys array cannot contain a null value.");
068         entries[i] = new SimpleMapEntry(i);
069   }
070   }
071
072   @Override /* Map */
073   public Set<Map.Entry<K,V>> entrySet() {
074      return asSet(entries);
075   }
076
077   @Override /* Map */
078   public V get(Object key) {
079      for (int i = 0; i < keys.length; i++)
080         if (keys[i].equals(key))
081            return values[i];
082      return null;
083   }
084
085   @Override /* Map */
086   public Set<K> keySet() {
087      return asSet(keys);
088   }
089
090   @Override /* Map */
091   public V put(K key, V value) {
092      for (int i = 0; i < keys.length; i++) {
093         if (keys[i].equals(key)) {
094            V v = values[i];
095            values[i] = value;
096            return v;
097         }
098      }
099      throw new IllegalArgumentException("No key '"+key+"' defined in map");
100   }
101
102   class SimpleMapEntry implements Map.Entry<K,V> {
103
104      private int index;
105
106      SimpleMapEntry(int index) {
107         this.index = index;
108      }
109
110      @Override /* Map.Entry */
111      public K getKey() {
112         return keys[index];
113      }
114
115      @Override /* Map.Entry */
116      public V getValue() {
117         return values[index];
118      }
119
120      @Override /* Map.Entry */
121      public V setValue(V val) {
122         V v = values[index];
123         values[index] = val;
124         return v;
125      }
126   }
127}