1. 程式人生 > >集合遍歷過程中刪除集合元素問題

集合遍歷過程中刪除集合元素問題

集合遍歷過程中如何刪除集合元素,,這個問題應該很簡單,用迭代器即可;

public static void main(String[] args) {
        List<String> strList = new ArrayList<String>();
        strList.add("aa");
        strList.add("bb");
        strList.add("cc");
        System.out.println(strList);
        Iterator<String> it = strList.iterator();
        while (it.hasNext()) {
            String str = it.next();
            if ("bb".equals(str)) {
                it.remove();
            }
        }
        System.out.println(strList);
    }

列印結果:

[aa, bb, cc]
[aa, cc]

對於上面這個問題就不多做贅述了;

來看下面的程式碼:

public static void main(String[] args) {
        List<String> strList = Arrays.asList("aa", "bb", "cc");
        System.out.println(strList);
        Iterator<String> it = strList.iterator();
        while (it.hasNext()) {
            String str = it.next();
            if ("bb".equals(str)) {
                it.remove();
            }
        }
        System.out.println(strList);
    }
列印結果:

Exception in thread "main" java.lang.UnsupportedOperationException
[aa, bb, cc]
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at Collection.ListTest.main(ListTest.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

這個是之前碰到的問題,,當時沒怎麼注意,換了種實現方式就沒管了;

為什麼會出現這種狀況呢?去仔細翻了下原始碼就理解了;

看Arrays原始碼得知

List<String> strList = Arrays.asList("aa", "bb", "cc");

這裡的strList物件不是我們常用的java.util.ArrayList的例項物件,而是Arrays的靜態內部類ArrayList的例項物件;

    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    /**
     * @serial include
     */
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }

        @Override
        public int size() {
            return a.length;
        }

        @Override
        public Object[] toArray() {
            return a.clone();
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            int size = size();
            if (a.length < size)
                return Arrays.copyOf(this.a, size,
                                     (Class<? extends T[]>) a.getClass());
            System.arraycopy(this.a, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }

        @Override
        public E get(int index) {
            return a[index];
        }

        @Override
        public E set(int index, E element) {
            E oldValue = a[index];
            a[index] = element;
            return oldValue;
        }

        @Override
        public int indexOf(Object o) {
            E[] a = this.a;
            if (o == null) {
                for (int i = 0; i < a.length; i++)
                    if (a[i] == null)
                        return i;
            } else {
                for (int i = 0; i < a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        @Override
        public boolean contains(Object o) {
            return indexOf(o) != -1;
        }

        @Override
        public Spliterator<E> spliterator() {
            return Spliterators.spliterator(a, Spliterator.ORDERED);
        }

        @Override
        public void forEach(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            for (E e : a) {
                action.accept(e);
            }
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            E[] a = this.a;
            for (int i = 0; i < a.length; i++) {
                a[i] = operator.apply(a[i]);
            }
        }

        @Override
        public void sort(Comparator<? super E> c) {
            Arrays.sort(a, c);
        }
    }

看原始碼得知,,這裡的ArrayList(Arrays的靜態內部類)沒有覆蓋/重寫java.util.AbstractList的iterator()方法,,所以呼叫的是AbstractList的iterator()方法;

接下來看一看java.util.AbstractList的部分對應原始碼:

public Iterator<E> iterator() {
        return new Itr();
    }
private class Itr implements Iterator<E> {
        /**
         * Index of element to be returned by subsequent call to next.
         */
        int cursor = 0;

        /**
         * Index of element returned by most recent call to next or
         * previous.  Reset to -1 if this element is deleted by a call
         * to remove.
         */
        int lastRet = -1;

        /**
         * The modCount value that the iterator believes that the backing
         * List should have.  If this expectation is violated, the iterator
         * has detected concurrent modification.
         */
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size();
        }

        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

看到這裡,Arrays的靜態內部類ArrayList的例項物件strList呼叫iterator()生成的物件,實際上是這裡Itr的物件例項;

故執行報錯程式碼while迴圈中呼叫的remove()方法也是Itr的remove()方法,而由上面的程式碼可以發現,這裡remove的實現靠的是

AbstractList.this.remove(lastRet);
即呼叫的是AbstractList本身的remove()方法,再去看AbstractList的原始碼;
/**
     * {@inheritDoc}
     *
     * <p>This implementation always throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
     */
    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }

    /**
     * {@inheritDoc}
     *
     * <p>This implementation always throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
     */
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }

    /**
     * {@inheritDoc}
     *
     * <p>This implementation always throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
     */
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }

可以看到AbstractList中並沒有實現對應的set、add、remove方法,而是直接丟擲了UnsupportedOperationException異常,這個與之前打印出來的輸出結果吻合;

最後再來看看java.util.Arrays$ArrayList的原始碼;

雖然繼承了java.util.AbstractList抽象類,但是並沒有重寫其add、remove等方法,只能做一些簡單的取值遍歷操作;

private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }

        @Override
        public int size() {
            return a.length;
        }

        @Override
        public Object[] toArray() {
            return a.clone();
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            int size = size();
            if (a.length < size)
                return Arrays.copyOf(this.a, size,
                                     (Class<? extends T[]>) a.getClass());
            System.arraycopy(this.a, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }

        @Override
        public E get(int index) {
            return a[index];
        }

        @Override
        public E set(int index, E element) {
            E oldValue = a[index];
            a[index] = element;
            return oldValue;
        }

        @Override
        public int indexOf(Object o) {
            E[] a = this.a;
            if (o == null) {
                for (int i = 0; i < a.length; i++)
                    if (a[i] == null)
                        return i;
            } else {
                for (int i = 0; i < a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        @Override
        public boolean contains(Object o) {
            return indexOf(o) != -1;
        }

        @Override
        public Spliterator<E> spliterator() {
            return Spliterators.spliterator(a, Spliterator.ORDERED);
        }

        @Override
        public void forEach(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            for (E e : a) {
                action.accept(e);
            }
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            E[] a = this.a;
            for (int i = 0; i < a.length; i++) {
                a[i] = operator.apply(a[i]);
            }
        }

        @Override
        public void sort(Comparator<? super E> c) {
            Arrays.sort(a, c);
        }
    }


相關推薦

集合過程刪除集合元素問題

集合遍歷過程中如何刪除集合元素,,這個問題應該很簡單,用迭代器即可; public static void main(String[] args) { List<String> strList = new ArrayList<String

Java_集合過程刪除集合元素報錯的解決方案

問題描述:使用增強for迴圈遍歷集合,如果遍歷過程中去除第一個或者最後一個元素會報錯,去除中間的元素不會報錯:Exception in thread “main” java.util.ConcurrentModificationException 不知道這個是

集合過程iterator, 添加刪除元素報異常

exc asn 一致性 使用 遍歷 one mov exceptio 刪除 list set 遍歷過程中添加或者刪除元素,報異常。 使用iterator 也會報異常 ConcurrentModificationException remove只能用叠代器的remov

如何正確在集合的時候刪除多個元素

前言 不管是集合中的遍歷還是刪除集合中元素,這些操作相比大家都很熟悉,但是在日常開發中,我們有時候會遇到在集合遍歷的時候刪除集合中的元素。那麼這裡面有什麼哪些小竅門呢?為什麼標題上說是刪除多個元素,難倒刪除多個元素和刪除單個元素有什麼區別? 常見的for

Map集合過程呼叫remove方法引起的問題

Set<Integer> set2 = map2.keySet(); for(Integer key :set2) { if(key>50 && key<1

C#List並刪除某個元素的方法

ffffff nbsp 句柄 實現 padding 分析 win html round 本文實例分析了C#遍歷List並刪除某個元素的方法。分享給大家供大家參考。具體如下: 1、我們選擇用for循環:for(int i=0;i<list.count;i++) {

list在過程的add/remove

com index 遍歷集合 很多 pub iterator clas util http 平時開發過程中,很多人估計都遇到過一個問題:在遍歷集合的的過程中,進行add或者remove操作的時候,會出現2類錯誤,包括:java.util.ConcurrentModifica

python list並刪除部分元素

python 遍歷list並刪除部分元素 有兩個list,list_1 為0-9,list_2 為0-4,需要刪除list_1中包含在list_2中的元素 list_1 =[] for i in range(10): list_1.append(str(i)) list

初學者在python序列同時刪除相鄰元素時的易錯點

(1)問題的案例 以列表List為例 現在有一個列表,我想要遍歷它,然後判斷每個元素是否滿足某個條件而需要被刪除,如下面一段程式碼: test = [11,22,33,44,55,66] for temp in test: if temp == 22 or t

如何實現在集合過程刪除其中的元素

為了進行測試,下面是取自MatLab中的一段小程式,其中第2行是計算集合的長度,第三行是從後往前遍歷集合的MatLab專用語法,第5行是刪除第j個元素。 function res = testDel

java集合刪除指定元素異常分析總結

它的 一次 但是 代碼 元素 拋出異常 源碼 刪除指定元素 test 在使用集合的過程中,我們經常會有遍歷集合元素,刪除指定的元素的需求,而對於這種需求我們往往使用會犯些小錯誤,導致程序拋異常或者與預期結果不對,本人很早之前就遇到過這個坑,當時沒註意總結,結果前段時間又遇到

集合刪除行不行

package 演算法; import java.util.ArrayList; import java.util.List; public class 集合遍歷中刪除行不行 {     /**      * 面試中會問到lis

JavaList集合的三種方式

asn tex iter for nbsp next next() ray string 首先創建一個List集合: List<String> list = new ArrayList<String>();list.add("name"); list

Java的Map集合以及Map集合例項

文章目錄 一、Map集合 二、Map集合遍歷例項 一、Map集合 Map<K,V>k是鍵,v是值 1、 將鍵對映到值的物件,一

java集合的向下轉型、泛型

java中集合儲存字串時,集合的get(i)方法是獲取集合中的第i+1個元素,而這個元素是Object型別,而Object型別沒有length()方法,遍歷的時候如果直接.length()會報錯。如果想使用字串的方法,就必須把元素還原成字元(向下轉型)。 集合的遍歷。其實就是依次獲取集合

實際開發,解決列印iReport獲取list集合,並且縮小間距

用iReport做列印的時候,在後端程式碼中得到map集合後,map中存放list 用$F獲取屬性,欄屬性代表每行的空、間隔 /*** * * @author xxx * @param checkVisaReqVo *

將一個集合類的某一欄位到另一個集合

        我們在開發中經常會遇到這種情況,就是在查詢一個列表的時候,可能會需要將另一個表中的某些欄位拼接到這一個列表中,在這種時候,如果是取到列表之後,然後根據某一個欄位再去一個一個的查詢的話,就會很費資源,介面也會變的很慢。   &nbs

mybatis的配置檔案使用兩個或多個foreach進行多個集合的問題

<select id="selectTrafficEventIngByType" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> f

迭代器迭代元素,迭代器修改元素集合集合元素集合修改元素解決併發修改異常

import java.util.ArrayList;import java.util.List;import java.util.ListIterator;public class TextDemo1

javascriptEL表示式List集合的值

今天遇到個問題就是我想在js中獲取後臺傳來的list中的值。本來頁面展現是用的EL表示式,一切都沒有什麼問題,但是我要動態獲取集合中的url然後在js中呼叫qrcode生成二維碼,當我嘗試按大部分的思