1

我需要一些帮助来理解这里发生的事情。我在将元素插入 Map 时收到“IndexOutOfBoundsException”。这里是堆栈跟踪。

 java.lang.IndexOutOfBoundsException: Index: 192, Size: 192
        at java.util.ArrayList.RangeCheck(ArrayList.java:547)
        at java.util.ArrayList.get(ArrayList.java:322)
        at somepackage.SequentialMap.getKey(Unknown Source)
        at somepackage.SequentialIterator.next(Unknown Source)
        at java.util.HashMap.buildCache(HashMap.java:590)
        at java.util.HashMap.resize(HashMap.java:576)
        at java.util.HashMap.addEntry(HashMap.java:939)
        at java.util.HashMap.put(HashMap.java:477)
        at somepackage.SequentialMap.put(Unknown Source)
        at somepackage.BatchBurstingInfo.parseContents(Unknown Source)
        at somepackage.BatchBurstingInfo.parse(Unknown Source)
        at somepackager.BatchBurstingInfo.setFileContents(Unknown Source)
        at somepackage.BurstingListBean.setMembers(Unknown Source)

上面的 SeqentialMap 扩展了 HashMap 。
在这里,我们试图插入一个大于 200 的对象列表。问题是当我在使用 JDK 1.6 的开发设置中运行时它工作正常,但在 weblogic 服务器中,我总是在相同的步骤中得到这个异常。
另外,在调试时,我在 HashMap 类中找不到任何 buildCache 方法,这是否意味着 weblogic JDK 是一些不同版本的 og 实现。

这是代码片段

public class SequentialMap extends HashMap
{
    private ArrayList m_keys = new ArrayList();

    /**
     * Removes the mapping for this key from this map if present.
     *
     * @param  key key whose mapping is to be removed from the map.
     * @return previous value associated with specified key, or <tt>null</tt>
     *         if there was no mapping for key.  A <tt>null</tt> return can
     *         also indicate that the map previously associated <tt>null</tt>
     *         with the specified key.
     */
    public Object remove(Object key) 
    {
        synchronized(this)
        {
                if(m_keys != null)
            {
                int iSize = m_keys.size();
                ArrayList oNewArray = new ArrayList();
                for(int i = 0; i < iSize; i++)
                {
                        if(m_keys.get(i).equals(key) == false)
                    {
                            oNewArray.add(m_keys.get(i));
                    }
                }
                m_keys = oNewArray;
            }
            return super.remove(key);
        }
    }   

    /**
     * Returns a collection view of the values contained in this map.  The
     * collection is backed by the map, so changes to the map are reflected in
     * the collection, and vice-versa.  The collection supports element
     * removal, which removes the corresponding mapping from this map, via the
     * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
     * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
     *
     * @return a collection view of the values contained in this map.
     */
    /*public Collection values() 
    {
    }*/
    /**
     * Returns a collection view of the mappings contained in this map.  Each
     * element in the returned collection is a <tt>Map.Entry</tt>.  The
     * collection is backed by the map, so changes to the map are reflected in
     * the collection, and vice-versa.  The collection supports element
     * removal, which removes the corresponding mapping from the map, via the
     * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
     * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
     *
     * @return a collection view of the mappings contained in this map.
     * @see Map.Entry
     */
    public Set entrySet() 
    {
            return super.entrySet();
    }

    /**
     * Removes all mappings from this map.
     */
    public void clear() 
    {
            synchronized(this)
        {
            m_keys.clear();
            super.clear();
        }
    }

    /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for this key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated.
     * @param value value to be associated with the specified key.
     * @return previous value associated with specified key, or <tt>null</tt>
     *         if there was no mapping for key.  A <tt>null</tt> return can
     *         also indicate that the HashMap previously associated
     *         <tt>null</tt> with the specified key.
     */
    public Object put(Object key, Object value) 
    {
        int iExistingIndex = this.getKeyIndex(key);
        Object oldObj = super.put(key, value);
        if(iExistingIndex == -1)
        {
            m_keys.add(key);
        }
        else
        {
                m_keys.add(iExistingIndex, key);
        }

        return oldObj;
    }

    /**
     * Returns a set view of the keys contained in this map.  The set is
     * backed by the map, so changes to the map are reflected in the set, and
     * vice-versa.  The set supports element removal, which removes the
     * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
     * <tt>clear</tt> operations.  It does not support the <tt>add</tt> or
     * <tt>addAll</tt> operations.
     *
     * @return a set view of the keys contained in this map.
     */
    public Set keySet() 
    {
        Set oSet = super.keySet();
        final SequentialMap oThis = this;
        HashSet oNewSet = new HashSet(oSet){
            /**
             * Returns an iterator over the elements in this set.  The elements
             * are returned in no particular order.
             *
             * @return an Iterator over the elements in this set.
             * @see ConcurrentModificationException
             */
            public Iterator iterator() {
                return new SequentialIterator(oThis);
            }
        };

        return oNewSet;
    }

    protected int getKeyIndex(Object key)
    {
        int index = -1;

            if(m_keys != null)
        {
            int iSize = m_keys.size();
            for(int i = 0; i < iSize; i++)
            {
                if(m_keys.get(i).equals(key))
                {
                        index = i;
                        break;
                }
            }
        }

        return index;
    }

    Object getKey(int index)
    {
            return m_keys.get(index);
    }
}



class SequentialIterator implements Iterator
{
    private SequentialMap m_oMap = null;
    private int m_iCurrentIndex = 0;

        SequentialIterator(SequentialMap oMap)
    {
            this.m_oMap = oMap;
    }
    /**
     * Returns <tt>true</tt> if the iteration has more elements. (In other
     * words, returns <tt>true</tt> if <tt>next</tt> would return an element
     * rather than throwing an exception.)
     *
     * @return <tt>true</tt> if the iterator has more elements.
     */
    public boolean hasNext() {
            return (m_iCurrentIndex < m_oMap.size());
    }
    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration.
     * @exception NoSuchElementException iteration has no more elements.
     */
    public Object next() {
        Object key = m_oMap.getKey(m_iCurrentIndex);
        m_iCurrentIndex++;
        return key;
    }
    /**
     *
     * Removes from the underlying collection the last element returned by the
     * iterator (optional operation).  This method can be called only once per
     * call to <tt>next</tt>.  The behavior of an iterator is unspecified if
     * the underlying collection is modified while the iteration is in
     * progress in any way other than by calling this method.
     *
     * @exception UnsupportedOperationException if the <tt>remove</tt>
     *        operation is not supported by this Iterator.

     * @exception IllegalStateException if the <tt>next</tt> method has not
     *        yet been called, or the <tt>remove</tt> method has already
     *        been called after the last call to the <tt>next</tt>
     *        method.
     */
    public void remove() {
            Object key = m_oMap.getKey(m_iCurrentIndex - 1);
        m_oMap.remove(key);
    }
}
4

1 回答 1

1

我猜您的 Weblogic 使用的是旧版本的 JRockit。我检查了最后一个版本的源代码,他们不再使用这个 buildCache。

我不确定,但我认为如果你替换它:

public boolean hasNext() {
        return (m_iCurrentIndex < m_oMap.size());
}

对于这个实现:

public boolean hasNext() {
        return (m_iCurrentIndex < m_keys.size());
}

你不会有这个错误。

NoSuchElementException如果没有下一个元素,您还需要抛出一个on next() 方法,而不是抛出一个IndexOutOfBoundsException当前实现正在执行的操作。

添加这样的东西

if (!hasNext()) {
    throw new NoSuchElementException();
}
于 2012-04-09T08:03:50.523 回答