首先收一下fail-fast 是什么 我认为这个就是一种理念 就是先考虑最坏的结果 然后直接抛出异常停止
在我们写代码的时候经常会这样写 比如
public int divide(int a,int b){ if (b==0){ throw new RuntimeException("除数不能为0"); } return a/b; }
上面代码使用 用a除以b 我们首先会对b进行校验 这就是fail-fast机制
如何删除arrayList 中的元素
1.
List<String> list=new ArrayList<String>(5){{ add("张三"); add("张三"); add("李四"); add("张三"); add("王五"); }}; //普通for 循环删除张字开头的 for (int i = 0; i < list.size(); i++) { if (list.get(i).startsWith("张")) { list.remove(i); } } list.forEach(list1-> System.out.println(list1));
为什么有姓张的没有被删除因为ArrayList 是基于数组实现当删除前面的元素后面会自动向前 而我们的下标继续往后 所以就漏掉了
2.使用增强for
List<String> list=new ArrayList<String>(5){{ add("张三"); add("张三"); add("李四"); add("张三"); add("王五"); }}; for (String s : list) { if (s.startsWith("张")) { list.remove(s); } } list.forEach(list1-> System.out.println(list1));
此时会报一个并发修改异常 这就是上面所说的fail-fase 机制
现在我们查看这个checkForCommodification方法
是在这里判断进行报错的
那么这里的 modCount和expectedModCount是什么?
modCount是ArrayList中的一个成员变量。它表示该集合实际被修改的次数。
expectedModCount 是 ArrayList中的一个内部类——Itr中的成员变量。expectedModCount表示这个迭代器预期该集合被修改的次数。其值随着Itr被创建而初始化。只有通过迭代器对集合进行操作,该值才会改变。
上面代码中调用remove方法进行删除
他只让modCount++ 进行了一个佳佳 没有对excep 进行加加 所以当调用 checkForCommodification方法 时就报 一个并发修改的异常
3 使用迭代器进行删除
List<String> list=new ArrayList<String>(5){{ add("张三"); add("张三"); add("李四"); add("张三"); add("王五"); }}; Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ String next = iterator.next(); if (next.startsWith("张")) { iterator.remove(); } } list.forEach(list1-> System.out.println(list1));
4.还可以直接使用 之前说过的stream 流的filter
List<String> list=new ArrayList<String>(5){{ add("张三"); add("张三"); add("李四"); add("张三"); add("王五"); }}; list = list.stream().filter(ele -> !ele.startsWith("张")).collect(Collectors.toList()); list.forEach(list1-> System.out.println(list1));
5.还可以使用一些安全的集合 比如 CopyOnWriteArrayList 写入数据的时候会复制出来一个副本 当前读时还是读取的之前的集合 在这个副本中进行写入 写入成功后替换原来的集合 这种会有读取的延迟 使用了一种读写分离的思想。