范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

为什么阿里巴巴强制不要在foreach里执行删除操作

  那天,小二去阿里面试,面试官老王一上来就甩给了他一道面试题:为什么阿里的 Java 开发手册里会强制不要在 foreach 里进行元素的删除操作?小二听完就面露喜色,因为两年前,也就是 2021 年,他在《Java 程序员进阶之路》专栏上的第 63 篇看到过这题。
  PS:star 这种事,只能求,不求没效果,铁子们,《Java 程序员进阶之路》在 GitHub 上已经收获了 437 枚星标,小伙伴们赶紧去点点了,冲 500 star!
  https://github.com/itwanger/toBeBetterJavaer
  为了镇楼,先搬一段英文来解释一下 fail-fast。
  In systems design, a fail-fast system is one which immediately reports at its interface any condition that is likely to indicate a failure. Fail-fast systems are usually designed to stop normal operation rather than attempt to continue a possibly flawed process. Such designs often check the system"s state at several points in an operation, so any failures can be detected early. The responsibility of a fail-fast module is detecting errors, then letting the next-highest level of the system handle them.
  这段话的大致意思就是,fail-fast 是一种通用的系统设计思想,一旦检测到可能会发生错误,就立马抛出异常,程序将不再往下执行。  public void test(Wanger wanger) {        if (wanger == null) {         throw new RuntimeException("wanger 不能为空");     }          System.out.println(wanger.toString()); }
  一旦检测到 wanger 为 null,就立马抛出异常,让调用者来决定这种情况下该怎么处理,下一步  wanger.toString()  就不会执行了——避免更严重的错误出现。
  很多时候,我们会把 fail-fast 归类为 Java 集合框架的一种错误检测机制,但其实 fail-fast 并不是 Java 集合框架特有的机制。
  之所以我们把 fail-fast 放在集合框架篇里介绍,是因为问题比较容易再现。  List list = new ArrayList<>(); list.add("沉默王二"); list.add("沉默王三"); list.add("一个文章真特么有趣的程序员");  for (String str : list) {  if ("沉默王二".equals(str)) {   list.remove(str);  } }  System.out.println(list);
  这段代码看起来没有任何问题,但运行起来就报错了。
  根据错误的堆栈信息,我们可以定位到 ArrayList 的第 901 行代码。  final void checkForComodification() {     if (modCount != expectedModCount)         throw new ConcurrentModificationException(); }
  也就是说,remove 的时候触发执行了  checkForComodification  方法,该方法对 modCount 和 expectedModCount 进行了比较,发现两者不等,就抛出了 ConcurrentModificationException  异常。
  为什么会执行  checkForComodification  方法呢?
  是因为 for-each 本质上是个语法糖,底层是通过迭代器 Iterator 配合 while 循环实现的,来看一下反编译后的字节码。  List list = new ArrayList(); list.add("沉默王二"); list.add("沉默王三"); list.add("一个文章真特么有趣的程序员"); Iterator var2 = list.iterator();  while(var2.hasNext()) {     String str = (String)var2.next();     if ("沉默王二".equals(str)) {         list.remove(str);     } }  System.out.println(list);
  来看一下 ArrayList 的 iterator 方法吧:  public Iterator iterator() {     return new Itr(); }
  内部类 Itr 实现了 Iterator 接口。  private class Itr implements Iterator {     int cursor;       // index of next element to return     int lastRet = -1; // index of last element returned; -1 if no such     int expectedModCount = modCount;      Itr() {}      public boolean hasNext() {         return cursor != size;     }      @SuppressWarnings("unchecked")     public E next() {         checkForComodification();         int i = cursor;         Object[] elementData = ArrayList.this.elementData;         if (i >= elementData.length)             throw new ConcurrentModificationException();         cursor = i + 1;         return (E) elementData[lastRet = i];     } }
  也就是说  new Itr()  的时候 expectedModCount 被赋值为 modCount,而 modCount 是 List 的一个成员变量,表示集合被修改的次数。由于 list 此前执行了 3 次 add 方法。 add 方法调用 ensureCapacityInternal 方法  ensureCapacityInternal 方法调用 ensureExplicitCapacity 方法  ensureExplicitCapacity 方法中会执行  modCount++
  所以 modCount 的值在经过三次 add 后为 3,于是  new Itr()  后 expectedModCount 的值也为 3。
  执行第一次循环时,发现"沉默王二"等于 str,于是执行  list.remove(str) 。 remove 方法调用 fastRemove 方法  fastRemove 方法中会执行  modCount++  private void fastRemove(int index) {     modCount++;     int numMoved = size - index - 1;     if (numMoved > 0)         System.arraycopy(elementData, index+1, elementData, index,                          numMoved);     elementData[--size] = null; // clear to let GC do its work }
  modCount 的值变成了 4。
  执行第二次循环时,会执行 Itr 的 next 方法( String str = (String) var3.next(); ),next 方法就会调用 checkForComodification  方法,此时 expectedModCount 为 3,modCount 为 4,就只好抛出 ConcurrentModificationException 异常了。
  那其实在阿里巴巴的 Java 开发手册里也提到了,不要在 for-each 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式。
  那原因其实就是我们上面分析的这些,出于 fail-fast 保护机制。
  那该如何正确地删除元素呢 ?
  1)remove 后 break  List list = new ArrayList<>(); list.add("沉默王二"); list.add("沉默王三"); list.add("一个文章真特么有趣的程序员");  for (String str : list) {  if ("沉默王二".equals(str)) {   list.remove(str);   break;  } }
  break 后循环就不再遍历了,意味着 Iterator 的 next 方法不再执行了,也就意味着  checkForComodification  方法不再执行了,所以异常也就不会抛出了。
  但是呢,当 List 中有重复元素要删除的时候,break 就不合适了。
  2)for 循环  List list = new ArrayList<>(); list.add("沉默王二"); list.add("沉默王三"); list.add("一个文章真特么有趣的程序员"); for (int i = 0, n = list.size(); i < n; i++) {  String str = list.get(i);  if ("沉默王二".equals(str)) {   list.remove(str);  } }
  for 循环虽然可以避开 fail-fast 保护机制,也就说 remove 元素后不再抛出异常;但是呢,这段程序在原则上是有问题的。为什么呢?
  第一次循环的时候,i 为 0, list.size()  为 3,当执行完 remove 方法后,i 为 1,list.size()  却变成了 2,因为 list 的大小在 remove 后发生了变化,也就意味着"沉默王三"这个元素被跳过了。能明白吗?
  remove 之前  list.get(1)  为"沉默王三";但 remove 之后 list.get(1)  变成了"一个文章真特么有趣的程序员",而 list.get(0)  变成了"沉默王三"。
  3)使用 Iterator  List list = new ArrayList<>(); list.add("沉默王二"); list.add("沉默王三"); list.add("一个文章真特么有趣的程序员");  Iterator itr = list.iterator();  while (itr.hasNext()) {  String str = itr.next();  if ("沉默王二".equals(str)) {   itr.remove();  } }
  为什么使用 Iterator 的 remove 方法就可以避开 fail-fast 保护机制呢?看一下 remove 的源码就明白了。  public void remove() {     if (lastRet < 0)         throw new IllegalStateException();     checkForComodification();      try {         ArrayList.this.remove(lastRet);         cursor = lastRet;         lastRet = -1;         expectedModCount = modCount;     } catch (IndexOutOfBoundsException ex) {         throw new ConcurrentModificationException();     } }
  删除完会执行  expectedModCount = modCount ,保证了 expectedModCount 与 modCount 的同步。
  简单地总结一下,fail-fast 是一种保护机制,可以通过 for-each 循环删除集合的元素的方式验证这种保护机制。
  那也就是说,for-each 本质上是一种语法糖,遍历集合时很方面,但并不适合拿来操作集合中的元素(增删)。  原文链接:https://mp.weixin.qq.com/s/QxV79Rbhv1Hua7pIR8zLJA
  原作者:沉默王二

商用自动洗碗机的特点自动洗碗机是否好用,都必须从不同的角度判断,如方便程度,价格是否符合大多数消费者要求,安装是否方便等等。今天,从洗碗机价格和性能两方面简单介绍。自动洗碗机方便吗?自动洗碗机通常具有餐饮行业自动洗碗机餐具通常是餐饮管理的重点和薄弱环节,许多餐馆都有餐具损坏率高和洗碗不干净现象。餐具损坏和清洁餐具不干净不仅降低餐具的质量,而且增加了成本,也影响了公众形象和健康安全保护。客户不愿意自动洗碗机操作的注意事项中大型餐饮机构用洗碗机洗碗,原本需要34个人做的工作量,现在两个人就可以轻松完成,把碗放在洗碗机里,然后把它拿出来,节省时间和繁琐的过程,让洗碗不再枯燥繁琐。正确使用和定期维护洗碗商用洗碗机的分类及工作原理商用洗碗机有平铺式和长龙式,商用洗碗机受到许多酒店,连锁餐厅,学校和其他餐饮公司的青睐。虽然商用洗碗机可用于不同的规格,尺寸,不同材料的餐具清洗,但由于清洁差异,效果不同。陶瓷餐具餐饮自动洗碗机的优缺点现在在餐饮行业,自动洗碗机已经是非常普遍的,无论是酒店还是自助餐厅食堂厅,都可能需要商用洗碗机。市场上自动洗碗机的价格一般为数万元元。根据产品质量,价格从数万到数十万不等。如何购买自动洗碗机的功能特点使用全自动洗碗机清洗餐具并操作正确,清洁程度可以达到98。人工洗涤干净的餐具,即使你看到表面明亮清洁,实际上也有你看不到的细菌和病毒。因此,只有自动洗碗机有效的消毒,让食客吃饭更放揭盖式洗碗机的特性1。清洗全封闭洗涤,无需抹布,切断细菌传播路径。2,消毒使用加热和专业洗涤消毒剂,可杀死大肠杆菌,沙氏门菌等病毒。3,干燥洗涤后直接干燥,避免留下的水痕,使餐具更加光滑。4,存储容是否有必要使用自动洗碗机?为什么餐厅,食堂,酒店需要洗碗机?简单地说,酒店,餐厅采用自动洗碗机,提高洗碗工作效率,减少洗碗工的劳动强度,同时保障了食客的健康。洗碗机和人工洗碗的优势是什么?使用洗碗机洗碗筷,商用自动洗碗机与人工洗碗对比与人工洗涤相比,洗碗机的洗碗速度具有相当大的优势,并且自动洗碗机的清洁速度甚至可以超过5个洗碗工。食堂洗碗机已成为许多酒店和餐馆所需的厨房设备之一。在水和电力方面,自动洗碗机的平均商用自动洗碗机的特点一般而言,自动洗碗机包含自动除渣,自动清洁,自动喷淋冲洗,自动烘干等功能,清洁后的餐具可以直接使用。随着中国消费结构的升级,洗碗机已成为家电行业增长较快的类别之一。自动洗碗机进行科洗碗机和人工洗碗的优势对比为什么餐厅,食堂,酒店等地方需要用到洗碗机?简单地说,酒店餐厅采用自动洗碗机,提高洗碗的工作效率,降低洗碗工的劳动强度,确保食客的健康。洗碗机和人工洗碗的优势是什么?使用洗碗机清洗
教培教父俞敏洪自救再造100个薇娅李佳琦?我尊重命运的安排,但从不屈服于命运的专制,今年9月,60岁生日时,俞敏洪曾如此坦白自己的心境。作为教培时代的教父,俞敏洪清醒且自知,他曾将个人的成功归因于时代,认为人都是时代的产物手机不贴膜,不带壳的下场首先上图这是我刚买不久的iQoonew5为什么买这手机呢哈哈。正是因为王者荣耀这款游戏所以买了它。捂脸捂脸真的是不带套一时爽,出了事两眼泪汪汪泪奔泪奔泪奔泪奔。我买的是iqoone没有宽带照样可以让WIFI覆盖,蒲公英X4C开箱体验前言随着科学技术的发展,我们现在必须要承认的一个很现实的问题就是每个人对于网络的依赖性越来越大,生活中没有网络总感觉少了点什么,毕竟我们平时的工作和学习中,网络对于我们的帮助确实很中城院要案中心苏宁易购危机涉及的四大法律问题苏宁易购不管愿不愿意,主不主动,都必须正视四大重大法律问题第一,对照中华人民共和国中小企业促进法第六条,长期拖欠作为中小微企业的供应商货款,是否违反法律?第二,对照中华人民共和国证甘肃省明年年底前建成高速公路充电网络来源新甘肃我省明年年底前建成高速公路充电网络每日甘肃网兰州讯(新甘肃甘肃日报记者王占东通讯员李明)日前,国网甘肃综合能源服务有限公司与甘肃省高速公路服务有限公司签订充电站建设合作协汽车新零售瞄准换购市场,大搜车与两桶油擦出新火花稳定增加汽车消费成为2021年汽车流通行业的重要工作。今年以来,国家相关部委开展新一轮新能源汽车下乡活动,汽车产业流通提速。与此同时,民众对汽车消费的体验需求也越来越高,市场急需便120W1亿像素却是千元价,小米价格不用你砍,我自己降大家都知道小米手机是手机中的性价比之王,当初雷军创立小米的时候,定位就是专为发烧友而生。小米也因此经常被称为堆料狂魔。比如前不久发布的RedmiNote11Pro,虽然是千元机,但华为麒麟芯片5G手机,现货机型还有哪些?价格是多少?众所周知,华为手机业务因为美国的制裁,今年的手机出货量大幅下滑,现在市面上要想买到一个华为5G手机,真的有点难,主要原因是华为5G麒麟芯片库存紧张,5G手机的货源自然也就不多,华为逆袭!被苹果剔除的欧菲光迎来了好消息!央视说的果然没有错欧菲光终于翻身了!昨天看一个报道说苹果目前是每秒3000美元的营收进账,是当下最为赚钱的公司。其实这似乎都是人人都知道的事情,不管是苹果手机系列还是平板或是电脑系列,都能够拥有自己财政部提前下达2022年中央引导地方科技发展资金预算20。68亿元来源人民网原创稿人民网北京12月1日电(记者王震)据财政部网站消息,近日,财政部印发通知,提前下达2022年中央引导地方科技发展资金预算20。68亿元,统筹用于支持有关省(自治区直华硕无畏Pro14锐龙版续航实测办公娱乐肝满4小时,结局舒适了对于有移动办公需求的用户来说,一款轻薄本往往扮演着得力助手的角色,而该笔电除了要有足够好的性能轻薄便携的机身以外,其续航能力同样也要满足办公一族全天的使用需求,否则工作图中断电或寻