如何一邊循環(huán)一邊刪除數(shù)組中的元素系冗?
坑1
請看如下代碼:
/**
* 測試刪除集合中的空白元素
*/
@Test
public void removeBlank() {
? ? List<String> list = new ArrayList<>();
? ? list.add("1");
? ? list.add("2");
? ? list.add("3");
? ? list.add(" ");
? ? list.add("? ");
? ? for (String s : list) {
? ? ? ? if (StringUtils.isBlank(s)) {
? ? ? ? ? ? list.remove(s);
? ? ? ? }
? ? }
? ? System.out.println("list:" + list);
}
輸出結(jié)果:list:[1, 2, 3, ] 宇挫∨嗜可以看到空白元素沒有刪除干凈。
請看如下代碼:
/**
* 測試刪除集合中的空白元素
*/
@Test
public void removeBlank() {
? ? List<String> list = new ArrayList<>();
? ? list.add("1");
? ? list.add("2");
? ? list.add("3");
? ? list.add(" ");
? ? list.add("? ");
? ? Iterator<String> iterator = list.iterator();
? ? while (iterator.hasNext()) {
? ? ? ? String s = iterator.next();
? ? ? ? if (StringUtils.isBlank(s)) {
? ? ? ? ? ? iterator.remove();
? ? ? ? }
? ? }
? ? System.out.println("list:" + list);
}
結(jié)果輸出:list:[1, 2, 3]火俄。解決辦法其實(shí)就是用Iterator迭代器代替for循環(huán)芥吟。但是這個(gè)解決方法里還是隱藏了一個(gè)坑。
請看如下代碼:
/**
* 測試刪除集合中的空白元素
*/
@Test
public void removeBlank() {
? ? List<String> list = Arrays.asList("1","2","3",""," ");
? ? Iterator<String> iterator = list.iterator();
? ? while (iterator.hasNext()) {
? ? ? ? String s = iterator.next();
? ? ? ? if (StringUtils.isBlank(s)) {
? ? ? ? ? ? iterator.remove();
? ? ? ? }
? ? }
? ? System.out.println("list:" + list);
}
結(jié)果會直接報(bào)錯(cuò):java.lang.UnsupportedOperationException院塞。意思是不支持remove操作。
只是把list的定義換成了Arrays.asList击孩,卻有完全不一樣的運(yùn)行結(jié)果迫悠,非常神奇鹏漆。查看Arrays.asList的源碼:
/**
* Returns a fixed-size list backed by the specified array.? (Changes to
* the returned list "write through" to the array.)? This method acts
* as bridge between array-based and collection-based APIs, in
* combination with {@link Collection#toArray}.? The returned list is
* serializable and implements {@link RandomAccess}.
*
* <p>This method also provides a convenient way to create a fixed-size
* list initialized to contain several elements:
* <pre>
*? ? List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
* </pre>
*
* @param <T> the class of the objects in the array
* @param a the array by which the list will be backed
* @return a list view of the specified array
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
? ? return new ArrayList<>(a);
}
單從代碼看:return new ArrayList<>(a);應(yīng)該是一個(gè)普通的ArrayList肮摇?艺玲!查看注釋:返回一個(gè)固定大小的list括蝠!也就是說add和remove操作肯定會報(bào)錯(cuò)。同時(shí)也說明了這里的ArrayList不是我們平時(shí)使用的ArrayList饭聚。繼續(xù)跟蹤這個(gè)ArrayList:
/**
* @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);
? ? }
? ? ...
}
原來此處的ArrayList是Arrays的一個(gè)實(shí)現(xiàn)了AbstractList的內(nèi)部類忌警,并且沒有覆蓋add和remove方法,默認(rèn)這2個(gè)方法是會直接報(bào)“UnsupportedOperationException”的秒梳。
既然明白了報(bào)錯(cuò)原因法绵,解決辦法也很明顯了:
/**
* 測試刪除集合中的空白元素
*/
@Test
public void removeBlank() {
? ? List<String> list = Arrays.asList("1","2","3",""," ");
? ? List<String> result= new ArrayList<>(list);
? ? Iterator<String> iterator = result.iterator();
? ? while (iterator.hasNext()) {
? ? ? ? String s = iterator.next();
? ? ? ? if (StringUtils.isBlank(s)) {
? ? ? ? ? ? iterator.remove();
? ? ? ? }
? ? }
? ? System.out.println("list:" + result);
}
通過踩這幾個(gè)坑,再次驗(yàn)證了一個(gè)真理:在設(shè)計(jì)一個(gè)對外方法的時(shí)候酪碘,一點(diǎn)要謹(jǐn)慎處理集合和數(shù)組朋譬。因?yàn)槟阌肋h(yuǎn)不知道客戶端傳給你的集合是什么,也不知道客戶端是否會有對此集合有任何其他的不可控的操作兴垦。所以在使用客戶端傳遞的集合對象時(shí)徙赢,最好拷貝一個(gè)新集合后再操作。
轉(zhuǎn)載自