zoukankan      html  css  js  c++  java
  • 自己实现ArrayList

    在ArrayList源码中主要的两个属性是 Object数组和元素个数,

    elementData 用transient修饰的原因:当数组长度为10,这时候只有5个元素,默认序列化会占用10个空间。用transient修饰后,再重写writeOjbect和readObject可以自己定义序列化逻辑,节省空间
        transient Object[] elementData; 
    
        private int size;

    自己实现的 ArrayList, 少了很多检查,比如数组下标越界

    System.arraycopy(elementData, index + 1, elementData, index, numMoved);   这是个native方法

     Arrays.copyOf(elementData, newCapacity);  这个方法内部是转调System.arraycopy方法

    在源码中数组扩容是增加为原来的1.5倍,扩容时候用到了>> 右移操作,就是将一个数减少一半。假如数组初始大小为1,会做额外的判断

    public class MyArrayList<E> implements Iterable<E> {
    
        Object[] elementData;
    
        int size;
    
        public MyArrayList() {
            elementData = new Object[10];
            size = 0;
        }
    
        public void add(Object obj) {
            ensureExplicitCapacity(size + 1);
            elementData[size++] = obj;
        }
    
        private void ensureExplicitCapacity(int minCapacity) {
            if (size == elementData.length) {
                // 原来本身elementData容量大小 2
                int oldCapacity = elementData.length;
                // 新数据容量大小 (oldCapacity >> 1)=oldCapacity/
                int newCapacity = oldCapacity + (oldCapacity >> 1);// (2+2/2)=3
                // 如果初始容量为1的时候,那么他扩容的大小为多少呢?
                if (newCapacity - minCapacity < 0)
                    newCapacity = minCapacity; // 最少保证容量和minCapacity一样
                // 将老数组的值赋值到新数组里面去
                elementData = Arrays.copyOf(elementData, newCapacity);
            }
        }
    
        public Object remove(int index) {
            Object object = get(index);// index 2
            // 计算删除元素后面的长度
            int numMoved = size - index - 1; // 5
            // 2.删除原理 使用arraycopy往前移动数据,将最后一个变为空
            if (numMoved > 0)
                System.arraycopy(elementData, index + 1, elementData, index, numMoved);
            elementData[--size] = null; // 将最后一个元素变为空
            return object;
        }
    
        public Object get(int index) {
            return elementData[index];
        }
    
        @Override
        public Iterator<E> iterator() {
            Iterator<E> iterator = new Iterator<E>() {
                int index = 0;
    
                @Override
                public boolean hasNext() {
                    if (index < size) {
                        return true;
                    } else {
                        return false;
                    }
                }
    
                @SuppressWarnings("unchecked")
                @Override
                public E next() {
                    return (E) elementData[index++];
                }
            };
            return iterator;
        }
    
        public static void main(String[] args) {
    
            MyArrayList<Integer> list = new MyArrayList<Integer>();
            for (int i = 10; i < 23; i++) {
                list.add(i);
            }
    
            Iterator<Integer> iterator = list.iterator();
            while (iterator.hasNext()) {
                System.out.print(iterator.next() + "   ");
            }
            System.out.println();
            System.out.println(list.get(5));
    
            list.remove(6);
            Iterator<Integer> iterator2 = list.iterator();
            while (iterator2.hasNext()) {
                System.out.print(iterator2.next() + "   ");
            }
    
        }
    }
  • 相关阅读:
    逗号表达式
    Windows UninstallTool(右键卸载工具) 方便、快捷卸载电脑中的软件
    获取 Python 模块的路径
    Py2exe 打包后图标不显示[转载]
    获取系统文件关联图标
    py2exe 打包的exe,添加管理员权限
    获取注册表某键下的所有子键
    [已解决]Python脚本运行出错:libs\chardet\universaldetector.py:90: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode
    Git使用
    SQL Server获取指定行(如第二行)的数据
  • 原文地址:https://www.cnblogs.com/moris5013/p/11062832.html
Copyright © 2011-2022 走看看