zoukankan      html  css  js  c++  java
  • 数组、List、迭代器

    数组

    • 数组创建与初始化

      格式:className[] cn = new className[]{};
      可以省略{},但必须在[]里表明长度(变量必须提供维度表达式或数组初始值设定项),可以不用new,直接使用{}初始化,数组在创建时指定长度后只能一个一个的填充数组,不能使用{ }填充数组

      优点:访问效率高

      缺点:数组长度固定

      1. 数组在方法内可以不初始化(自动初始化,例:int-->0)

      2. 在创建数组时其类型与数组长度固定(编译时检查,这是与其他容器类的不同之处)

      3. 可以使用length查看数组的长度(这是数组唯一可以调用的)

      4. 数组可以持有基本类型,容器的泛型不可以,但是有自动包装机制

      5. 数组引用指向堆中真实对象,对象中保存其他对象的引用

    • 可变参数列表

      编译器会把可变参数列表当做数组,所以可以进行foreach,可以对可以参数列表传入数组

    • Arrays

        sort(T[] t); //必须是基本类型或者实现Comparable接口的类型,否则出现异常,基本类型使用快排,引用类型使用稳定归并
        asList(T... a); //接收的可变参数,返回的是List接口类型的数据,不能强转为List的其他实现类
        fill(); //用指定数据填充整个数组
        binarySearch(); //对已排序的数组查找,使用二分查找
        copyof(); //拷贝数组,底层使用的是 System.arraycopy(): 浅复制: 复制对象的引用, 比for循环快很多, 因为for循环是对对象本身的拷贝(用于ArrayList数组的扩容),   System.arraycopy()方法是native方法, 无法看到源码(应该是C/C++实现的)
      

    集合

    • 创建集合时不跟泛型

      编译器检查不出元素的类型,取元素时需要强转,若强转类型不对则报异常

    • 使用Arrays.asList()生成的List

      进行add()或delet()操作运行时会出异常,因为Arrays.asList()的底层为数组,长度不可改变

    • 分类

      • Collection

        1. List

          ArrayList LinkedList

        2. set

        3. queue

      • map


    List

    • 特点

      1. 允许元素重复
      2. 记录元素的位置
    • 区别

      ArrayList: 底层数据机构为数组, 随机访问较快, 增删操作较慢

      LinkedList: 底层数据结构为链表,增删较快,随机访问较慢


    ArrayList

    • 随机访问元素较快, 不擅长操作插入删除

    • add(int index, E element) 将指定的元素插入此列表中的指定位置。

        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }
      

      初始化容量: 创建ArrayList时构造器初始化一个空数组, 当使用add()时, 把数组容量变为静态字段 DEFAULT_CAPACITY=10

        private static int calculateCapacity(Object[] elementData, int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            }
            return minCapacity;
        }
        private void ensureCapacityInternal(int minCapacity) {
            ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
        }
        private void ensureExplicitCapacity(int minCapacity) {
            modCount++;
            // overflow-conscious code
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
        }
      

      1.5倍扩容 : 使用System.arraycopy进行扩容,每次扩容oldCapacity >> 1,位运算右移变为oldCapacity的一半,所以扩容为原来的1.5倍

        private void grow(int minCapacity) {
            // overflow-conscious code
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            if (newCapacity - minCapacity < 0)
                newCapacity = minCapacity;
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
      
    • remove() 移除指定数据数-----底层使用System.arraycopy进行数据挪移

    • 线程不安全:
      List list = Collections.synchronizedList(new ArrayList(...));//进行同步

    • 容量大小和元素个数的关系??-----ArrayList里面有个int size表明当前的元素个数, 每次add元素就会进行size++, 当元素个数等于容量时就会扩容

    • default关键字(虚拟扩展方法), 可以在接口里对方法实现, List接口实现了sort()方法


    迭代器

    Iterator

    1. boolean hasNext() 如果仍有元素可以迭代,则返回 true
    2. E next() 返回迭代的下一个元素
    3. void remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)
    4. default void forEachRemaining(Consumer<? super E> action)

    ArrayList迭代器如下

    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;
    
        public boolean hasNext() {
            return cursor != size;
        }
    
        @SuppressWarnings("unchecked")
        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];
        }
    
    • 不允许在foreach里删除或添加(来自<<阿里巴巴Java开发手册>>)

        List<String> a = new ArrayList<>();
        a.add("1");
        a.add("2");
        for (String string : a) {
        	if("2".equals(string)) {
        		a.remove(string);
        	}
        	System.out.printlb(String);
        }
      

    异常: java.util.ConcurrentModificationException

    **分析:**
    
    1. remove("1")
    
    	第一轮: cussor=0,size=2,取出"1"后cussor+1,删除"1"后size=1
    
    	第二轮: cussor=1,size=1, 经hasNext()判断结束循环,元素"2"没有得到遍历
    
    2. remove("2")
    
    	第一轮: cussor=0,size=2,取出"1"后cussor+1,size不变 
    
    	第二轮: cussor=1,size=2, 取出"2"后cussor+1,删除"2"后size=1
    	
    	第三轮: cussor=2,size=1,hasNext()为true不能结束循环,此时进入next()方法内的checkForComodification()方法就抛出异常
    
    **解决:**
    
    	List<String> list = new ArrayList<>(); 
    	list.add("1"); 
    	list.add("2"); 
    	Iterator<String> iterator = list.iterator(); 
    	while (iterator.hasNext()) { 
    		String item = iterator.next(); 
    		if (item.equals"2") { 
    			iterator.remove(); 
    		} 
    	}
    

    LinkedList

    • LinkedList中的链表节点:

        private static class Node<E> {
            E item;
            Node<E> next;
            Node<E> prev;
      
            Node(Node<E> prev, E element, Node<E> next) {
                this.item = element;
                this.next = next;
                this.prev = prev;
            }
        } 
      

    • 方法:

      普通增删查: LinkedList的相比于ArrayList一般多First和Last方法

      : 后进先出

            push(): 往栈底(列表最后)压入数据
      
            pop(); 取出栈顶数据(列表开始)
      
            peek()  获取列表第一个元素,peekFirst   peekLast
            
            poll() 获取第一个元素并移除改元素 pollFIrst  pollLast
      

  • 相关阅读:
    互联网搜索引擎——文本预处理
    nltk的pos_tag
    nltk.stem 词干提取(stemming)
    python3的encode和decode涉及的str和bytes转换
    power rails 'GND' and 'VCC/VDD' are interconnected in net VCC
    impot不能导入自己写的python文件【爆红】
    No module named 'tensorflow.contrib'
    解决spark-submit的There is insufficient memory for the Java Runtime Environment to continue.(老顽固问题) failed; error='Cannot allocate memory' (errno=12)
    spark的standalone模式下:查看任务结束后的历史记录
    只是为了保存一些有用链接而已
  • 原文地址:https://www.cnblogs.com/mdc1771344/p/9928480.html
Copyright © 2011-2022 走看看