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轉化為不可變的集合,Collections也提供了這樣的方法,最終轉化為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)境下使用,或者在需要保護列表免受修改的場景下使用。
總結
到此這篇關于java.lang.UnsupportedOperationException分析及解決辦法的文章就介紹到這了,更多相關java.lang.UnsupportedOperationException內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
java8 stream的多字段排序實現(xiàn)(踩坑)
這篇文章主要介紹了java8 stream的多字段排序實現(xiàn)(踩坑),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03
SpringBoot?整合mapstruct的實現(xiàn)步驟
這篇文章主要介紹了SpringBoot整合mapstruct,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11
Java開發(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

