探究map,list,for

从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("----");
View Code

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 //        }
View Code

 可见,遍历数组使用的是原始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     }
View Code

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 输出无变换
View Code

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());
View Code

但是可以修改对象的属性

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         }
View Code

数组的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     }
View Code

可以理解为,这也就体现了迭代器的作用

反正别人这样说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配链表,就这样撒。

原文地址:https://www.cnblogs.com/woainixxx/p/13185587.html