一个有序的key-value器皿NamedList_MQ, Tuxedo及OLTP讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MQ, Tuxedo及OLTP讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3167 | 回复: 0   主题: 一个有序的key-value器皿NamedList        下一篇 
renruishen
注册用户
等级:新兵
经验:58
发帖:79
精华:0
注册:2011-12-25
状态:离线
发送短消息息给renruishen 加好友    发送短消息息给renruishen 发消息
发表于: IP:您无权察看 2014-11-3 14:45:16 | [全部帖] [楼主帖] 楼主

     一个有序的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);




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论