java.lang.UnsupportedOperationException分析及解決辦法
今天在寫業(yè)務的時候,需要對從數(shù)據(jù)庫返回的List集合根據(jù)對象屬性進行排序,那么常規(guī)的做法就是使用Collections的sort方法,實現(xiàn)Compartor接口重寫compare方法,或者直接使用該list的sort方法,但是無論使用那種方法都遇到了這樣的報錯原因:
java.lang.UnsupportedOperationException: null
at java.util.Collections$UnmodifiableList.sort(Collections.java:1333) ~[na:1.8.0_331]
at java.util.Collections.sort(Collections.java:177) ~[na:1.8.0_331]
無法支持的操作,再看報錯第二行UnmodifiableList,這是一個不可變的集合,它繼承 UnmodifiableCollection類,UnmodifiableCollection 中涉及到元素改動(新增、刪除、清空…)的方法都直接拋出 UnsupportedOperationException 異常,并不改動元素;Iterator 中涉及到元素修改的方法也一樣不進行元素的改動。
那么是不是把這個集合變成可變的集合問題是不就解決了呢?
list = new ArrayList<>(list);
在排序前給這個list再次封裝,問題得以解決。
static class UnmodifiableList<E> extends UnmodifiableCollection<E> implements List<E> { private static final long serialVersionUID = -283967356065247728L; final List<? extends E> list; UnmodifiableList(List<? extends E> list) { super(list); this.list = list; } public boolean equals(Object o) {return o == this || list.equals(o);} public int hashCode() {return list.hashCode();} public E get(int index) {return list.get(index);} public E set(int index, E element) { throw new UnsupportedOperationException(); } public void add(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); } public int indexOf(Object o) {return list.indexOf(o);} public int lastIndexOf(Object o) {return list.lastIndexOf(o);} public boolean addAll(int index, Collection<? extends E> c) { throw new UnsupportedOperationException(); } @Override public void replaceAll(UnaryOperator<E> operator) { throw new UnsupportedOperationException(); } @Override public void sort(Comparator<? super E> c) { throw new UnsupportedOperationException(); } public ListIterator<E> listIterator() {return listIterator(0);} public ListIterator<E> listIterator(final int index) { return new ListIterator<E>() { private final ListIterator<? extends E> i = list.listIterator(index); public boolean hasNext() {return i.hasNext();} public E next() {return i.next();} public boolean hasPrevious() {return i.hasPrevious();} public E previous() {return i.previous();} public int nextIndex() {return i.nextIndex();} public int previousIndex() {return i.previousIndex();} public void remove() { throw new UnsupportedOperationException(); } public void set(E e) { throw new UnsupportedOperationException(); } public void add(E e) { throw new UnsupportedOperationException(); } @Override public void forEachRemaining(Consumer<? super E> action) { i.forEachRemaining(action); } }; } public List<E> subList(int fromIndex, int toIndex) { return new UnmodifiableList<>(list.subList(fromIndex, toIndex)); } /** * UnmodifiableRandomAccessList instances are serialized as * UnmodifiableList instances to allow them to be deserialized * in pre-1.4 JREs (which do not have UnmodifiableRandomAccessList). * This method inverts the transformation. As a beneficial * side-effect, it also grafts the RandomAccess marker onto * UnmodifiableList instances that were serialized in pre-1.4 JREs. * * Note: Unfortunately, UnmodifiableRandomAccessList instances * serialized in 1.4.1 and deserialized in 1.4 will become * UnmodifiableList instances, as this method was missing in 1.4. */ private Object readResolve() { return (list instanceof RandomAccess ? new UnmodifiableRandomAccessList<>(list) : this); } }
這里從UnmodifiableList的源碼來分析:除了equals、hashCode、get、indexOf、lastIndexOf等方法外,其他方法都會拋出UnsupportedOperationException()異常,而這些方法的共同點都是返回該list的屬性,說明UnmodifiableList是一個只讀的集合,因此對這個List不能進行添加或刪除元素等操作。
如果需要將list轉(zhuǎn)化為不可變的集合,Collections也提供了這樣的方法,最終轉(zhuǎn)化為UnmodifiableList。
public static <T> List<T> unmodifiableList(List<? extends T> list) { return (list instanceof RandomAccess ? new UnmodifiableRandomAccessList<>(list) : new UnmodifiableList<>(list)); }
同樣的 Collections 集合類中的 unmodifiableMap、unmodifiableSet也是只讀內(nèi)部類。它們可以在多線程環(huán)境下使用,或者在需要保護列表免受修改的場景下使用。
總結(jié)
到此這篇關(guān)于java.lang.UnsupportedOperationException分析及解決辦法的文章就介紹到這了,更多相關(guān)java.lang.UnsupportedOperationException內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java8 stream的多字段排序?qū)崿F(xiàn)(踩坑)
這篇文章主要介紹了java8 stream的多字段排序?qū)崿F(xiàn)(踩坑),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03JAVA并發(fā)中VOLATILE關(guān)鍵字的神奇之處詳解
這篇文章主要給大家介紹了關(guān)于JAVA并發(fā)中VOLATILE關(guān)鍵字的神奇之處的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-05-05SpringBoot?整合mapstruct的實現(xiàn)步驟
這篇文章主要介紹了SpringBoot整合mapstruct,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11Java開發(fā)環(huán)境jdk 1.8安裝配置方法(Win7 64位系統(tǒng)/windows server 2008)
這篇文章主要介紹了Java開發(fā)環(huán)境配置方法(Win7 64位系統(tǒng)/windows server 2008),需要的朋友可以參考下2016-10-10