首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

一个有序的key-value器皿NamedList

2012-10-21 
一个有序的key-value容器NamedList???????????????????????????????????????????????? 一个有序的key-valu

一个有序的key-value容器NamedList

???????????????????????????????????????????????? 一个有序的key-value容器NamedList

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

在读solr源代码的时候,看到一个有序的key-value容器类NamedList,挺有创意的。

?

一、特点:

?

1、key是可以重复的

2、容器中的元素是有序的(插入顺序)

3、可通过下标获取key和value

4、key和value都是可空的

?

二、适用场景

?

1、需要用上以上特点的场景。

2、从上面描述的特点,我们可以看出NamedList非常适合作为JSON格式的对象的序列化。

?

三、实现

?

实现挺简单的,简单来说就是在一个ArrayList里用第2n、2n+1(n=0、1、2...)个item为一对存放一个keyvalue对,

?

第2n个item存放name,第2n+1个item存放value(最多只能存放Interge.MAX_VALUE/2 个keyvalue对)。

?

然后实现了根据下标操作数据的方法,如:

?

  public String getName(int idx) {    return (String)nvPairs.get(idx << 1);  }  public T getVal(int idx) {    return (T)nvPairs.get((idx << 1) + 1);  }

???

?? 也实现了根据key对数据的操作,如

???

  public T get(String name) {    return get(name,0);  }

??? 但性能会比较差,因为需要从头开始一个一个元素去比较,来定位元素。

???

?

?

??? 附上NamedList的完整源代码:

???

/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */package org.apache.solr.common.util;import java.util.*;import java.io.Serializable;/** * A simple container class for modeling an ordered list of name/value pairs. * * <p> * Unlike Maps: * </p> * <ul> *  <li>Names may be repeated</li> *  <li>Order of elements is maintained</li> *  <li>Elements may be accessed by numeric index</li> *  <li>Names and Values can both be null</li> * </ul> * * <p> * A NamedList provides fast access by element number, but not by name. * </p> * <p> * When a NamedList is serialized, order is considered more important than access * by key, so ResponseWriters that output to a format such as JSON will normally * choose a data structure that allows order to be easily preserved in various * clients (i.e. not a straight map). * If access by key is more important, see {@link SimpleOrderedMap}, * or simply use a regular {@link Map} * </p> * * @version $Id: NamedList.java 779486 2009-05-28 08:48:29Z shalin $ */public class NamedList<T> implements Cloneable, Serializable, Iterable<Map.Entry<String,T>> {  protected final List nvPairs;  /** Creates an empty instance */  public NamedList() {    nvPairs = new ArrayList();  }  /**   * Creates a NamedList instance containing the "name,value" pairs contained in the   * Entry[].   *   * <p>   * Modifying the contents of the Entry[] after calling this constructor may change   * the NamedList (in future versions of Solr), but this is not garunteed and should   * not be relied upon.  To modify the NamedList, refer to {@link #add(String, Object)}   * or {@link #remove(String)}.   * </p>   *   * @param nameValuePairs the name value pairs   */  public NamedList(Map.Entry<String, ? extends T>[] nameValuePairs) {    nvPairs = nameValueMapToList(nameValuePairs);  }  /**   * Creates an instance backed by an explicitly specified list of   * pairwise names/values.   *   * <p>   * When using this constructor, runtime typesafety is only garunteed if the all   * even numbered elements of the input list are of type "T".   * </p>   *   * @param nameValuePairs underlying List which should be used to implement a NamedList   * @deprecated Use {@link #NamedList(java.util.Map.Entry[])} for the NamedList instantiation   */  @Deprecated  public NamedList(List nameValuePairs) {    nvPairs=nameValuePairs;  }  /**   * Method to serialize Map.Entry&lt;String, ?&gt; to a List in which the even   * indexed elements (0,2,4. ..etc) are Strings and odd elements (1,3,5,) are of   * the type "T".   *   * @param nameValuePairs   * @return Modified List as per the above description   * @deprecated This a temporary placeholder method until the guts of the class   * are actually replaced by List&lt;String, ?&gt;.   * @see https://issues.apache.org/jira/browse/SOLR-912   */  @Deprecated  private List  nameValueMapToList(Map.Entry<String, ? extends T>[] nameValuePairs) {    List result = new ArrayList();    for (Map.Entry<String, ?> ent : nameValuePairs) {      result.add(ent.getKey());      result.add(ent.getValue());    }    return result;  }  /** The total number of name/value pairs */  public int size() {    return nvPairs.size() >> 1;  }  /**   * The name of the pair at the specified List index   *   * @return null if no name exists   */  public String getName(int idx) {    return (String)nvPairs.get(idx << 1);  }  /**   * The value of the pair at the specified List index   *   * @return may be null   */  @SuppressWarnings("unchecked")  public T getVal(int idx) {    return (T)nvPairs.get((idx << 1) + 1);  }  /**   * Adds a name/value pair to the end of the list.   */  public void add(String name, T val) {    nvPairs.add(name);    nvPairs.add(val);  }  /**   * Modifies the name of the pair at the specified index.   */  public void setName(int idx, String name) {    nvPairs.set(idx<<1, name);  }  /**   * Modifies the value of the pair at the specified index.   * @return the value that used to be at index   */  public T setVal(int idx, T val) {    int index = (idx<<1)+1;    T old = (T)nvPairs.get( index );    nvPairs.set(index, val);    return old;  }  /**   * Removes the name/value pair at the specified index.   * @return the value at the index removed   */  public T remove(int idx) {    int index = (idx<<1);    nvPairs.remove(index);    return (T)nvPairs.remove(index);  // same index, as things shifted in previous remove  }  /**   * Scans the list sequentially beginning at the specified index and   * returns the index of the first pair with the specified name.   *   * @param name name to look for, may be null   * @param start index to begin searching from   * @return The index of the first matching pair, -1 if no match   */  public int indexOf(String name, int start) {    int sz = size();    for (int i=start; i<sz; i++) {      String n = getName(i);      if (name==null) {        if (n==null) return i; // matched null      } else if (name.equals(n)) {        return i;      }    }    return -1;  }  /**   * Gets the value for the first instance of the specified name   * found.   *   * @return null if not found or if the value stored was null.   * @see #indexOf   * @see #get(String,int)   */  public T get(String name) {    return get(name,0);  }  /**   * Gets the value for the first instance of the specified name   * found starting at the specified index.   *   * @return null if not found or if the value stored was null.   * @see #indexOf   */  public T get(String name, int start) {    int sz = size();    for (int i=start; i<sz; i++) {      String n = getName(i);      if (name==null) {        if (n==null) return getVal(i);      } else if (name.equals(n)) {        return getVal(i);      }    }    return null;  }  /**   * Gets the values for the the specified name   * @param name Name   * @return List of values   */  public List<T> getAll(String name) {    List<T> result = new ArrayList<T>();    int sz = size();    for (int i = 0; i < sz; i++) {      String n = getName(i);      if (name==n || (name!=null && name.equals(n))) {        result.add(getVal(i));      }    }    return result;  }  public String toString() {    StringBuilder sb = new StringBuilder();    sb.append('{');    int sz = size();    for (int i=0; i<sz; i++) {      if (i != 0) sb.append(',');      sb.append(getName(i));      sb.append('=');      sb.append(getVal(i));    }    sb.append('}');    return sb.toString();  }  /**   *   * Helper class implementing Map.Entry<String, T> to store the key-value   * relationship in NamedList (the keys of which are String-s)    *   * @param <T>   */  public static final class NamedListEntry<T> implements Map.Entry<String, T> {    public NamedListEntry() {    }    public NamedListEntry(String _key, T _value) {      key = _key;      value = _value;    }    public String getKey() {      return key;    }    public T getValue() {      return  value;    }    public T setValue(T _value) {      T oldValue = value;      value = _value;      return oldValue;    }    private String key;    private T value;  }  /**   * Iterates over the Map and sequentially adds it's key/value pairs   */  public boolean addAll(Map<String,T> args) {    for( Map.Entry<String, T> entry : args.entrySet() ) {      add( entry.getKey(), entry.getValue() );    }    return args.size()>0;  }  /** Appends the elements of the given NamedList to this one. */  public boolean addAll(NamedList<T> nl) {    nvPairs.addAll(nl.nvPairs);    return nl.size()>0;  }  /**   * Makes a <i>shallow copy</i> of the named list.   */  public NamedList<T> clone() {    ArrayList newList = new ArrayList(nvPairs.size());    newList.addAll(nvPairs);    return new NamedList<T>(newList);  }  //----------------------------------------  // Iterable interface  //----------------------------------------  /**   * Support the Iterable interface   */  public Iterator<Map.Entry<String,T>> iterator() {    final NamedList list = this;    Iterator<Map.Entry<String,T>> iter = new Iterator<Map.Entry<String,T>>() {      int idx = 0;      public boolean hasNext() {        return idx < list.size();      }      public Map.Entry<String,T> next() {        final int index = idx++;        Map.Entry<String,T> nv = new Map.Entry<String,T>() {          public String getKey() {            return list.getName( index );          }          @SuppressWarnings("unchecked")          public T getValue() {            return (T)list.getVal( index );          }          public String toString()          {          return getKey()+"="+getValue();          }      public T setValue(T value) {        return (T) list.setVal(index, value);      }        };        return nv;      }      public void remove() {        throw new UnsupportedOperationException();      }    };    return iter;  }  public T remove(String name) {    int idx = indexOf(name, 0);    if(idx != -1) return remove(idx);    return null;  }  @Override  public int hashCode() {    return nvPairs.hashCode();  }  @Override  public boolean equals(Object obj) {    if (!(obj instanceof NamedList)) return false;    NamedList nl = (NamedList) obj;    return this.nvPairs.equals(nl.nvPairs);  }}

?

?

热点排行