java变量-未分类

并发修改异常

ConcurrentModificationException 异常
  • 软件包是java.util包
  • 该异常类继承自RuntimeException异常
  • 当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常
  • 理解xhj:并发修改异常
并发修改异常:ConcurrentModificationException 发生问题的案例
// 29-ListDemo3
public class ListDemo3 {
    //需求:
    /*
    有一个集合,
    添加三个元素 hello、world、java,
    遍历集合,得到每一个元素,看有没有world这个元素,如果有则添加元素javaee
    * */
    public static void main(String[] args){
        List<String> list = new ArrayList<String>();  分析步骤1

        String s1 = "hello";
        String s2 = "world";
        String s3 = "java";

        list.add(s1);
        list.add(s2);
        list.add(s3);

        //采用for循环的形式遍历集合元素不报错
/*        for (int i = 0 ; i <list.size() ; i++){
            String s = list.get(i);
            if(s.equals("world")){
                list.add("javaee");
            }
        }*/

        //采用迭代器的形式
        Iterator<String> it = list.iterator();  分析步骤1
        while (it.hasNext()) {
            String s = it.next();
            if(s.equals("world")){
                list.add("javaee");  分析步骤1
            }
        }
        // 使用迭代器遍历集合元素会报错:ConcurrentModificationException
        System.out.println(list);
    }
}

原因分析:采用迭代器出现异常
主要:采用迭代器的形式,对集合进行add添加元素操作之后,modCount变量的数值会增加,exceptedModCount变量不变,集合对象.next方法获取集合变量的时候会执行checkForComodification()方法,比较modCount和exceptedModCount的数值,不相等会报ConcurrentModificationException异常。

1 首先是List接口,接着使用接口中定义的两个方法:iterator、add
public interface List<E> {
		Iterator<E> iterator();
		boolean add(E e);
}

2 最终创建对象,new的是ArrayList这个实现类的对象

public abstract class AbstractList<E>{
	protected transient int modCount = 0;
	此变量在AbstractList<E>类中
}

public class ArrayList<E> extends AbstractList<E>  implements List<E> {
	ArrayList实现了List这个接口,就需要重写List中的方法,例如:iterator、add

   public boolean add(E e) {
       ensureCapacityInternal(size + 1);  //自己测试显示内容
       elementData[size++] = e;
       return true;
       //视频显示内容
       modCount++;
       add(e,elementData,size);
       return true;
   }
	
	
   public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
    	int expectedModCount = modCount;
    	/*
    	expectedModCound:预期修改集合的次数
    	modCount:实际修改集合的次数
    	最开始执行时,两者数量相同
    	变量modCount来自AbstractList<E>中,且用protected修饰,则子类可以直接访问到父类的成员变量,所以最开始两个变量的值都是0
    	*/
    	/*
    	在实际代码运行中,
    	 if(s.equals("world")){
                list.add("javaee");  分析步骤1
            }
         上述代码一旦条件满足,就会执行集合添加元素的操作,
         按照视频内容理解:每执行一次add方法,modCount会自加一,但是expectedModCount变量不变,接着执行next方法就会执行checkForComodification方法判断两者不相同时就会抛出异常。
*/
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
        final void checkForComodification() {
            if (modCount != expectedModCount)
            // 此处出现问题的原因是 modCount = 修改集合的次数、expectedModCount = 预期修改集合的次数
                throw new ConcurrentModificationException();
        }
    }
}

3 分析 抛出异常的原因是it.next()方法执行,又调取checkForComodification()方法出现问题。

原因分析:采用for循环遍历集合元素不报错分析

使用for循环遍历,获取元素使用的是集合对象.get方法。
public class ArrayList<E> extends AbstractList<E> implements List<E> {
    public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }
    调用get方法并没有对modCount、exceptedModCount变量进行比较,即使更改了modCount变量的值,但是也不影响执行。
}

关于视频和自己练习中add方法不相同问题理解:

public class ArrayList<E> extends AbstractList<E>  implements List<E> {
	// ArrayList实现了List这个接口,就需要重写List中的方法,例如:iterator、add

//自己测试显示内容
   public boolean add(E e) {
       ensureCapacityInternal(size + 1);  
       elementData[size++] = e;
       return true;
   }
分析是否相同:主要通过追述方法具体实现
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    private void ensureExplicitCapacity(int minCapacity) {
      modCount++;
      别的没有看懂,但是有关于变量modCount的++

      // overflow-conscious code
      if (minCapacity - elementData.length > 0)
          grow(minCapacity);
  }
   private static int calculateCapacity(Object[] elementData, int minCapacity) {
     if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
         return Math.max(DEFAULT_CAPACITY, minCapacity);
     }
     return minCapacity;
 }
 //视频显示内容
  public boolean add(E e) {
       modCount++;
       add(e,elementData,size);
       return true;
  }

并发修改异常解决及分析总结
并发修改异常:ConcurrentModificationException
产生原因:迭代器遍历的过程中,通过集合对象修改集合中的元素,比如添加元素(对象.add),造成了迭代器获取元素中判断预期修改值和实际修改值不一致
解决方法:用for循环遍历,然后用集合对象做对应的操作(对象.get)

冒泡排序

排序
将一组数据按照固定的规则进行排序

冒泡排序
一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,依次对所有数据进行操作,直至所有数据按要求完成排序。

原理
①如果有n个数据进行排序,总共需要比较n-1次
②每一次比较完毕,下一次的比较就会少一个数据参与

案例:

public class ArrayDemo {
    public static void main(String[] args) {
        // 定义一个数组
        int[] arr = {24,69,80,57,13};
        System.out.println("排序前:" + arrayToString(arr));
        arrayToReversear(arr);
        System.out.println("排序后:" + arrayToString(arr));

    }
    //把数组中的元素按照指定的规则组成一个字符串:[元素1,元素2,...,元素n]
    public static String arrayToString(int[] arr){
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0 ; i <arr.length ; i ++){
            if(i == arr.length - 1){
                sb.append(arr[i]);
            }else{
                sb.append(arr[i]).append(", ");
            }
        }
        sb.append("]");
        String s = sb.toString();
        return s;
    }
    public static void arrayToReversear(int[] arr){
        int tep = 0;
        for (int i = 0 ; i < arr.length ; i++) {
            for (int j = 0; j < (arr.length - i - 1); j++) {
                if (arr[j] > arr[j + 1]) {
                    tep = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tep;
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值