推荐阅读hashmap的资料
https://blog.csdn.net/a314774167/article/details/100110216
从map中取数据的几种不同方式
1 HashMap<String, String> stringStringHashMap = new HashMap<>(); 2 stringStringHashMap.put("a","1"); 3 stringStringHashMap.put("b","2"); 4 stringStringHashMap.put("c","3"); 5 stringStringHashMap.put("d","4"); 6 7 long l1 = System.currentTimeMillis(); 8 for (String s:stringStringHashMap.values()){ 9 System.out.println("这里是: "+ s); 10 } 11 // Iterator var6 = stringStringHashMap.values().iterator(); 12 //编译后的代码实际上是这样,使用迭代器 13 // while(var6.hasNext()) { 14 // String s = (String)var6.next(); 15 // System.out.println("这里是: " + s); 16 //} 17 long l2 = System.currentTimeMillis(); 18 System.out.println(l2-l1); 19 System.out.println(); 20 21 long l3 = System.currentTimeMillis(); 22 for (Map.Entry<String,String> entry:stringStringHashMap.entrySet()){ 23 System.out.println("k: "+entry.getKey()+" v: "+entry.getValue()); 24 } 25 Iterator var10 = stringStringHashMap.entrySet().iterator(); 26 27 // while(var10.hasNext()) { 28 // Entry<String, String> entry = (Entry)var10.next(); 29 // System.out.println("k: " + (String)entry.getKey() + " v: " + (String)entry.getValue()); 30 // } 31 long l4 = System.currentTimeMillis(); 32 System.out.println(l4-l3); 33 System.out.println(); 34 35 36 Iterator<Entry<String, String>> iterator = stringStringHashMap.entrySet().iterator(); 37 while (iterator.hasNext()){ 38 Entry<String, String> next = iterator.next(); 39 System.out.println(next.getValue()); 40 } 41 // while(iterator.hasNext()) { 42 // Entry<String, String> next = (Entry)iterator.next(); 43 // System.out.println((String)next.getValue());这里编译是做的类型转换的 44 // } 45 System.out.println(); 46 47 stringStringHashMap.forEach((key,value)->{ 48 var a=value; 49 System.out.println(a); 50 }); 51 // stringStringHashMap.forEach((key, value) -> { 52 // System.out.println(value); 没有什么用的var一行可以直接省略 53 // }); 54 55 // 1.Map entries 56 Consumer<Entry<String, String>> action = System.out::println; 57 stringStringHashMap.entrySet().forEach(action); 58 // PrintStream var10000 = System.out; 59 // System.out.getClass(); 60 // Consumer<Entry<String, String>> action = var10000::println; 61 // 前三行反而会将那一行拆开 62 // stringStringHashMap.entrySet().forEach(action); 63 64 // 2.Map keys 65 Consumer<String> actionKeys = System.out::println; 66 stringStringHashMap.keySet().forEach(actionKeys); 67 68 // 3. Map values 69 Consumer<String> actionValues = System.out::println; 70 stringStringHashMap.values().forEach(actionValues); 71 72 System.out.println("----");
map的for循环都是用到了迭代器
遍历数组和集合的区别
1 String[] array = {"1", "2", "3"}; 2 for (String i : array) { 3 System.out.println(i); 4 } 5 // for(int var4 = 0; var4 < var3; ++var4) { 6 // String i = var2[var4]; 7 // System.out.println(i); 8 // } 9 10 11 ArrayList<String> list = new ArrayList<>(); 12 list.add("111"); 13 list.add("222"); 14 list.add("333"); 15 for (String i : list) { 16 System.out.println(i); 17 } 18 // Iterator var17 = list.iterator(); 19 // 20 // while(var17.hasNext()) { 21 // String i = (String)var17.next(); 22 // System.out.println(i); 23 // }
可见,遍历数组使用的是原始for循环,集合的话使用的是Iterator迭代器。
foreach里面是否可以删除添加list中的元素---》
foreach不可以删除/修改/增加 集合元素,而for可以
1 ArrayList<String> lista = new ArrayList<>(); 2 lista.add("111"); 3 lista.add("222"); 4 lista.add("333"); 5 6 // log.info(list.toString()); 7 System.out.println(lista.toString()); 8 System.out.println(lista.getClass()); 9 for (int i = 0; i < lista.size(); i++) { 10 lista.remove("222"); 11 System.out.println(i); 12 } 13 System.out.println(lista.toString()); 14 System.out.println(lista.getClass()); 15 System.out.println("----"); 16 17 ArrayList<String> listb = new ArrayList<>(); 18 listb.add("111"); 19 listb.add("222"); 20 listb.add("333"); 21 System.out.println(listb.toString()); 22 23 for (String i : listb) { 24 // listb.remove("222"); 25 26 27 // 不要在foreach循环里进行元素的remove/add操作,remove元素请使用Iterator方式。 28 // 29 // Negative example: 30 // List<String> originList = new ArrayList<String>(); 31 // originList.add("22"); 32 // for (String item : originList) { 33 // //warn 34 // list.add("bb"); 35 // } 36 // 37 // 38 // 39 // Positive example: 40 // Iterator<Integer> it=b.iterator(); 41 // while(it.hasNext()){ 42 // Integer temp = it.next(); 43 // if (delCondition) { 44 // it.remove(); 45 // } 46 // } 47 System.out.println(i); 48 } 49 System.out.println(listb.toString()); 50 // java.util.ConcurrentModificationException 报错, 51 52 System.out.println("========"); 53 54 ArrayList<String> listc = new ArrayList<>(); 55 listc.add("111"); 56 listc.add("222"); 57 listc.add("333"); 58 System.out.println(listc); 59 Iterator<String> it = listc.iterator(); 60 while (it.hasNext()) { 61 String next = it.next(); 62 63 // it.remove();//这里使用的是迭代器里面的remove()方法, 64 if (next.equals("222")) { 65 it.remove();//这里使用的是迭代器里面的remove()方法, 66 // // 当然如果使用list的remove方法在此删除质地感元素的话是成功的,比如:list.remove("222") 67 // } 68 } 69 System.out.println(listc); 70 71 72 } 73 }
https://blog.csdn.net/weixin_44056462/article/details/90769772
这里面需要理解一点底层的源码思想
https://blog.csdn.net/qq_40521656/article/details/90749927
1 ArrayList<String> list = new ArrayList<>(); 2 list.add("111"); 3 list.add("222"); 4 list.add("333"); 5 // log.info(list.toString()); 6 System.out.println(list); 7 for (String i : list) { 8 i="444"; 9 } 10 System.out.println(list); 11 输出无变换
foreach不能修改集合的元素
1 Student student=new Student(1,"huge"); 2 Student student1=new Student(1,"xiaoyao"); 3 List<Student> studentList=new ArrayList<Student>(); 4 studentList.add(student); 5 studentList.add(student1); 6 System.out.println(student.getName()); 7 System.out.println(student1.getName()); 8 for(Student stu:studentList) 9 { 10 stu.setName("jingtian"); 11 } 12 System.out.println(student.getName()); 13 System.out.println(student1.getName());
但是可以修改对象的属性
1、for与foreach都可以遍历数组/集合,不过for则在较复杂的循环中效率更高。
2、foreach不可以删除/修改集合元素,而for可以
3、foreach和for都可以修改duixiang里面的属性
所以相比较下来for循环更为灵活。
从这里我们可以学习迭代器模式https://www.runoob.com/design-pattern/iterator-pattern.html, 这也是好处啊:迭代器模式将存储数据和遍历数据的职责分离
还可以学习到数组虽然可以用foreach,但实际上编译的时候又成了普通的forhttps://www.cnblogs.com/slwenyi/p/6393366.html
观察使用迭代器成功删除集合元素的时候
第一次 第二次
注意这里,删除元素后,游标减1,lastr直接成-1,期望次数加1 第三次
注意:如果代码中的remove用的不是迭代器的删除功能,会导致一个提前退出的问题,listc.remove("222");,而将原来的集合增加一个元素,在用这个就会报错ConcurrentModificationException,因为---》下图中modCount(记录了对集合修改的次数)的值不等于expectedModCount(通过迭代器对集合修改的次数
https://www.cnblogs.com/YYCat/p/4675084.html
可以看源码
iterator的next和remove,以及check
1 @SuppressWarnings("unchecked") 2 public E next() { 3 checkForComodification(); 4 int i = cursor; 5 if (i >= size) 6 throw new NoSuchElementException(); 7 Object[] elementData = ArrayList.this.elementData; 8 if (i >= elementData.length) 9 throw new ConcurrentModificationException(); 10 cursor = i + 1; 11 return (E) elementData[lastRet = i]; 12 } 13 final void checkForComodification() { 14 if (modCount != expectedModCount) 15 throw new ConcurrentModificationException(); 16 } 17 18 public void remove() { 19 if (lastRet < 0) 20 throw new IllegalStateException(); 21 checkForComodification(); 22 23 try { 24 ArrayList.this.remove(lastRet); 注意这个实际是数组自己的remove 25 cursor = lastRet; 26 lastRet = -1; 27 expectedModCount = modCount; 28 } catch (IndexOutOfBoundsException ex) { 29 throw new ConcurrentModificationException(); 30 } 31 }
数组的remove方法
1 public E remove(int index) { 2 rangeCheck(index); 3 4 modCount++; 5 E oldValue = elementData(index); 6 7 int numMoved = size - index - 1; 8 if (numMoved > 0) 9 System.arraycopy(elementData, index+1, elementData, index, 10 numMoved); 11 elementData[--size] = null; // clear to let GC do its work 12 13 return oldValue; 14 }
可以理解为,这也就体现了迭代器的作用
反正别人这样说https://blog.csdn.net/layman1024/article/details/76103793,,我还没看到真的源码,线程,还没验证过,所以这里也不确定。
回归正题,取map中的值有哪些方式,他们的区别是啥,for和foreach,1.8的呢,能充分利用多核,实现真正的并行,如果数据量不大,只能起到简化代码的作用,而数据量大的时候,其威力就展现了。
for和foreach的效率……:(1)for是使用下标(偏移量)定位的.
(2)foreach应该是使用类似循环子的机构
(3)对随机访问效率高的ArrayList. 使用下标访问效率本身很高.foreach内部的循环子直接封装下标,自己实现的for比foreach更直接,效率稍高些,但差别不会太大,仍然在一个数量级上。 (4)如果使用插入和删除效率高的LinkedList,for基于下标访问会每次从头查询,效率会很低.foreach循环子使用高效的地址运算,效率会高.其差距将很大,完全不在一个数量级别.如果数组很大,差别可能会几百甚至上千倍.
为什么呢,下标定位,for配数组,链表结构foreach配链表,就这样撒。