list增删元素要用iterator,一直时知其然不知其所以然,今天把它基本搞明白了,其实很简单,半个小时绝对够自己验证一遍,只是一直懒得想。
先上结果:
这里测试了我能想到的7种方法,成功2种,分别是lambda 和 iterator。大家还有啥好方法也指点一下我把。
代码:
package group.zhangtao.iterator; import org.junit.Assert; import org.junit.Test; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; public class IteratorStudy { /** * 测试驱动 * @param function 测试用的function */ public void testFun(Function<List<String>, List<String>> function) { List<String> list = new LinkedList<>(); for (int i = 0; i < 100; i++) { list.add(UUID.randomUUID().toString()); } List<String> list1 = function.apply(list); Assert.assertEquals(0, list1.size()); } @Test public void testLambda() { testFun((list) -> list.stream() .filter(i -> false) .collect(Collectors.toList())); } @Test public void testIterator() { testFun((list) -> { //iterator true Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { iterator.next(); iterator.remove(); } return list; }); } @Test public void testFor0(){ testFun((list)->{ //for wrong for (int i = 0; i < list.size(); i++) { list.remove(list.get(i)); } return list; }); } @Test public void testFor1(){ testFun((list)->{ //for wrong for (int i = 0; i < list.size(); i++) { list.remove(i); } return list; }); } @Test public void testFor2(){ testFun((list)->{ //for wrong int size = list.size(); for (int i = 0; i < size; i++) { list.remove(i); } return list; }); } @Test public void testForI(){ testFun((list)->{ //fori wrong for (String s : list) { list.remove(s); } return list; }); } @Test public void testForEach(){ testFun((list)->{ //foreach wrong list.forEach(i -> list.remove(i)); return list; }); } }
public void testFun(Function<List<String>, List<String>> function) { List<String> list = new LinkedList<>(); for (int i = 0; i < 100; i++) { list.add(UUID.randomUUID().toString()); } List<String> list1 = function.apply(list); Assert.assertEquals(0, list1.size()); }
测试驱动构建一个list传入测试函数(lambda),测试函数会清空list,判断一下list的size是否为0即可。
直接报错的两个个方法不在赘述,是更新机制问题,别人讲了好多,大家可以搜搜看。
testfor2()数组越界,删除后list的size变小,不能指定删除,一直删除0号元素的话可以工作,但实际问题中没卵用。
这两个方法是一类问题:删除元素时size变小,所以只能遍历一半的元素(删的越少可遍到历的越多),以前经常被这种方法坑。
正确打开方式有两种:
@Test public void testIterator() { testFun((list) -> { //iterator true Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { iterator.next(); iterator.remove(); } return list; }); }
传统的iterator方式不断next->判断->remove
@Test public void testLambda() { testFun((list) -> list.stream() .filter(i -> false) .collect(Collectors.toList())); }
lambda表达式方式;
判断条件在过滤器里,
collect(Collectors.toList()))
这个函数会将过滤完的的结果转换为list
实际上并没有删除任何元素,只是新建了一个list,安全方便,易用。在不方便更换copyonwritearraylist的情况下相当于手动实现了一遍
缺点:只能删,不能增。