Java ArrayList用法总结_java中arraylist的用法-程序员宅基地

技术标签: java  Java初识  数组  数据结构  

ArrayList继承关系分析

ArrayList创建

使用com.google.common.collect包中Lists类,通过Lists的静态方法创建ArrayList,该类还可以创建其他的list,如LinkedList、CopyOnWriteArrayList等。

List<T> result = Lists.newArrayList();

ArrayList注释

ArrayList属于java.util包下。
进入到ArrayList.java,作者的注释如下:

/**
 * Resizable-array implementation of the <tt>List</tt> interface.  Implements
 * all optional list operations, and permits all elements, including
 * <tt>null</tt>.  In addition to implementing the <tt>List</tt> interface,
 * this class provides methods to manipulate the size of the array that is
 * used internally to store the list.  (This class is roughly equivalent to
 * <tt>Vector</tt>, except that it is unsynchronized.)
 *
 * ArrayList是list接口的可调整大小的数组实现类。实现了所有list的操作,并且允许元素是null。
 * 除了实现list接口, 该类提供了手动操作数组size的方法。该类大致与vector一致,但它是线程不安全的。
 * 
 * <p>The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>,
 * <tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant
 * time.  The <tt>add</tt> operation runs in <i>amortized constant time</i>,
 * that is, adding n elements requires O(n) time.  All of the other operations
 * run in linear time (roughly speaking).  The constant factor is low compared
 * to that for the <tt>LinkedList</tt> implementation.
 *
 * size,isEmpty,get,set,iterator和listIterator操作都是常量复杂度。add操作平均复杂度是常量,也就是说添加n个元素需要O(n)。
 * 所有其他操作大致是线性复杂度。常量因子比LinkedList实现类低。
 * 
 * <p>Each <tt>ArrayList</tt> instance has a <i>capacity</i>.  The capacity is
 * the size of the array used to store the elements in the list.  It is always
 * at least as large as the list size.  As elements are added to an ArrayList,
 * its capacity grows automatically.  The details of the growth policy are not
 * specified beyond the fact that adding an element has constant amortized
 * time cost.
 *
 * 每个ArrayList实例都有一个容量。容量是用于存储数组中元素的数组大小。容量保证至少大于数组的size。
 * 当添加元素到ArrayList时,它的容量会自动增长。扩容策略不确定,因为添加元素时消耗O(n)的时间。
 * 
 * <p>An application can increase the capacity of an <tt>ArrayList</tt> instance
 * before adding a large number of elements using the <tt>ensureCapacity</tt>
 * operation.  This may reduce the amount of incremental reallocation.
 *
 * 程序在向ArrayList实例添加大量元素前,可以先调用ensureCapacity方法扩容。这样会减少重分配空间的次数。
 *
 * <p><strong>Note that this implementation is not synchronized.</strong>
 * If multiple threads access an <tt>ArrayList</tt> instance concurrently,
 * and at least one of the threads modifies the list structurally, it
 * <i>must</i> be synchronized externally.  (A structural modification is
 * any operation that adds or deletes one or more elements, or explicitly
 * resizes the backing array; merely setting the value of an element is not
 * a structural modification.)  This is typically accomplished by
 * synchronizing on some object that naturally encapsulates the list.
 *
 * 注意该类是线程不安全的,即非同步的。如果多个线程同时访问一个ArrayList实例,方法外一定要保证同步,才能至少有一个线程可以修改list结构。
 * 修改list结构是指添加或删除一个或几个元素,或是显示调整数组大小,仅仅set一个元素值不算修改结构。
 * 这通常是在使用ArrayList的某个对象上完成同步操作。
 * 
 * If no such object exists, the list should be "wrapped" using the
 * {@link Collections#synchronizedList Collections.synchronizedList}
 * method.  This is best done at creation time, to prevent accidental
 * unsynchronized access to the list:<pre>
 *   List list = Collections.synchronizedList(new ArrayList(...));</pre>
 *
 * 如果不存在这样的对象(指上述在外部能保证同步的对象),list应该使用
 * Collections#synchronizedList Collections.synchronizedList此对象的包装类。最好在创建是使用此方法,以防访问时不同步。
 * List list = Collections.synchronizedList(new ArrayList(...));
 * 
 * <p><a name="fail-fast">
 * The iterators returned by this class's {@link #iterator() iterator} and
 * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:</a>
 * if the list is structurally modified at any time after the iterator is
 * created, in any way except through the iterator's own
 * {@link ListIterator#remove() remove} or
 * {@link ListIterator#add(Object) add} methods, the iterator will throw a
 * {@link ConcurrentModificationException}.  Thus, in the face of
 * concurrent modification, the iterator fails quickly and cleanly, rather
 * than risking arbitrary, non-deterministic behavior at an undetermined
 * time in the future.
 * 
 * 通过类的#iterator() iterator方法和通过#listIterator(int) listIterator方法返回的迭代器是快速失败的。
 * 如果在迭代器生成之后的任何时间使用除了ListIterator#remove() remove或者ListIterator#add(Object) add的方法来修改list结构,
 * 将会抛出ConcurrentModificationException异常。因此,面对并发修改时,迭代器会迅速干净的失败。
 * 而不是在未来不确定的时间里冒着武断、不确定性行为的风险。
 * 
 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
 * as it is, generally speaking, impossible to make any hard guarantees in the
 * presence of unsynchronized concurrent modification.  Fail-fast iterators
 * throw {@code ConcurrentModificationException} on a best-effort basis.
 * Therefore, it would be wrong to write a program that depended on this
 * exception for its correctness:  <i>the fail-fast behavior of iterators
 * should be used only to detect bugs.</i>
 * 
 * 请注意,无法保证迭代器的快速失效行为,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬保证。
 * 快速失败迭代器会尽可能抛出ConcurrentModificationException异常。
 * 因此编写依赖于此异常的正确性的程序是错误的,迭代器的Fail fast行为应仅用于检测错误。
 * 
 * <p>This class is a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @author  Josh Bloch
 * @author  Neal Gafter
 * @see     Collection
 * @see     List
 * @see     LinkedList
 * @see     Vector
 * @since   1.2
 */
 public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList继承关系

在这里插入图片描述
ArrayList继承了AbstractList抽象类,实现了List,RandomAccess,Cloneable,Serializable四个接口

Serializable接口:用来序列化和反序列化类。

Cloneable接口:可以使用Object.clone()方法,该方法实现对类实例进行按字段复制,没有实现该接口调用clone方法时会抛CloneNotSupporteddException异常。

RandomAccess接口:这只是一个内部没有方法的接口,仅作为一个标记接口存在,表示List集合下的实现支持快速随机访问功能。

List接口:包含很多方法,如size、isEmpty、contains、iterator等。

AbstractList抽象类:此类提供了List接口的基本实现,以最小化实现由“随机访问”数据存储(例如数组)支持的该接口所需的工作量。实现不可变List集合时,继承该类,并实现其中的get()、size()方法。实现可变List集合时,还需要实现其中的set()方法,如果集合是可变长度集合,需要override其add()和remove()方法。
modCount值保证快速失败机制。

其中ArrayList还有一些内部类,如Itr、ListItr、SubList、ArrayListSpliterator。
Itr实现了Iterator方法hasNext和next方法,重写remove和forEachRemaining方法。其中expectedModCount会初始化为modCount值,迭代时会判断expectedModCount和modCount是否相等,不相等则快速失败。
ListItr继承Itr,实现ListIterator。它实现了向前向后遍历,以及添加修改等方法。
SubList继承AbstractList,实现RandomAccess,是一个对ArrayList局部操作的集合。
ArrayListSpliterator实现Spliterator类,主要有三个方法:

//通过"二分法"分隔List集合
public ArrayListSpliterator<E> trySplit() 
//消费其中单个元素,此时index会相应+1
public boolean tryAdvance(Consumer<? super E> action)
//遍历所有未消费的集合元素
public void forEachRemaining(Consumer<? super E> action)            

代码如下:

public static void main(String[] args) throws InterruptedException {
    
    ArrayList<String> list1 = new ArrayList<>();
    list1.add("abc");
    list1.add("def");
    list1.add("hij");
    list1.add("klm");
    Spliterator spliterator = list1.spliterator();
    Spliterator trySplit = spliterator.trySplit();
    spliterator.forEachRemaining(str-> System.out.println(str));
    trySplit.forEachRemaining(str-> System.out.println(str));
}

输出结果:

hij
klm
abc
def

ArrayList的spliterator()方法返回的元素分隔符与ArrayList相同,但创建的分隔符为late-binding和fail-fast。 late-binding拆分器绑定到元素源,即Arraylist在第一次遍历/拆分/查询估计大小时,而不是在创建Spliterator时。
此外,它还可以单独和批量遍历元素。
分隔后,可以多线程地取遍历数组。

ArrayList常用方法

构造

ArrayList();//默认构造函数,提供初始容量为10的空数组
ArrayList(int initialCapacity);//构造指定初始容量的空数组
ArrayList(Collection<? extends E> c);//构造一个包含指定 collection 的元素的列表,元素顺序是该 collection 的迭代器返回顺序

代码如下:

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Main {
    

	//通过反射获取实际容量,即elementData的长度
    public static int getCapacity(ArrayList<?> arrayList) {
    
        Class<ArrayList> arrayListClass = ArrayList.class;
        try {
    
            Field field = arrayListClass.getDeclaredField("elementData");
            field.setAccessible(true);
            Object[] objects = (Object[])field.get(arrayList);
            return objects.length;
        } catch (Exception e) {
    
            e.printStackTrace();
            return -1;
        }
    }

    public static void main(String[] args) throws InterruptedException {
    
    	//空构造函数
        ArrayList<String> list1 = new ArrayList<>();
        //指定容量的构造函数
        ArrayList<String> list2 = new ArrayList<>(30);
        list1.add("abc");
        list1.add("def");
        list1.add("hij");
        //用其他collection初始化
        ArrayList<String> list3 = new ArrayList<>(list1);
        System.out.println("list1 = " + list1 + ",size = " + list1.size() + ", capacity = " +getCapacity(list1));
        System.out.println("list2 = " + list2+ ",size = " + list2.size() + ", capacity = " +getCapacity(list2));
        System.out.println("list3 = " + list3+ ",size = " + list3.size() + ", capacity = " +getCapacity(list3));
    }
}

输出如下:

list1 = [abc, def, hij],size = 3, capacity = 10
list2 = [],size = 0, capacity = 30
list3 = [abc, def, hij],size = 3, capacity = 3

从输出中也可以看到capacity的值的原则,空数组是默认10,指定容量即是指定的值。

添加

boolean add(E e);
void add(int index, E element);
boolean addAll(Collection<? extends E> c);
boolean addAll(int index, Collection<? extends E> c);

代码如下:

public static void main(String[] args) throws InterruptedException {
    
    ArrayList<String> list1 = new ArrayList<>();
    list1.add("abc");
    list1.add("def");
    //尾部追加元素
    list1.add("hij");
    System.out.println("list1 = " + list1);
    //在指定index增加元素
    list1.add(2, "xyz");
    System.out.println("list1 = " + list1);
    ArrayList<String> list2 = new ArrayList<>();
    list2.add("Willow");
    //批量增加元素
    list1.addAll(list2);
    System.out.println("list1 = " + list1);
    //在指定index批量增加元素
    list1.addAll(1,list2);
    System.out.println("list1 = " + list1);
}

输出如下:

list1 = [abc, def, hij]
list1 = [abc, def, xyz, hij]
list1 = [abc, def, xyz, hij, Willow]
list1 = [abc, Willow, def, xyz, hij, Willow]

遍历

public static void main(String[] args) throws InterruptedException {
    
    ArrayList<String> list1 = new ArrayList<>();
    list1.add("abc");
    list1.add("def");
    list1.add("hij");
    //通过for循环索引值取元素值
    for (int i = 0; i < list1.size(); i++) {
    
        System.out.print(list1.get(i));
    }
    System.out.println();
    //通过foreach遍历
    for (String str:list1
         ) {
    
        System.out.print(str);
    }
    System.out.println();
    //通过迭代器遍历
    Iterator iter = list1.iterator();
    while (iter.hasNext()){
    
        System.out.print(iter.next());
    }
}

输出如下:

abcdefhij
abcdefhij
abcdefhij

注意:遍历ArrayList时,通过索引序号访问效率最高,而使用迭代器的效率最低

修改元素值

public static void main(String[] args) throws InterruptedException {
    
    ArrayList<String> list1 = new ArrayList<>();
    list1.add("abc");
    list1.add("def");
    list1.add("hij");
    System.out.println("list1 = " + list1);
    //设置指定index的值为某个新值
    list1.set(2, "Willow");
    System.out.println("list1 = " + list1);
}

输出如下:

list1 = [abc, def, hij]
list1 = [abc, def, Willow]

删除

E remove(int index);
boolean remove(Object o);
void clear();
boolean removeAll(Collection<?> c);
boolean removeIf(Predicate<? super E> filter);
//通过迭代器删除

代码如下:

public static void main(String[] args) throws InterruptedException {
    
    ArrayList<String> list1 = new ArrayList<>();
    list1.add("abc");
    list1.add("def");
    list1.add("hij");
    list1.add("klm");
    list1.add("opq");
    list1.add("rst");
    System.out.println("list1 = " + list1);
    //删除指定index
    list1.remove(0);
    System.out.println("list1 = " + list1);
    //删除指定index
    list1.remove(0);
    System.out.println("list1 = " + list1);
    //删除指定元素
    list1.remove("rst");
    System.out.println("list1 = " + list1);
    //删除指定条件的元素
    list1.removeIf(str->str == "opq");
    System.out.println("list1 = " + list1);
    //情况
    list1.clear();
    System.out.println("list1 = " + list1);
}

输出如下:

list1 = [abc, def, hij, klm, opq, rst]
list1 = [def, hij, klm, opq, rst]
list1 = [hij, klm, opq, rst]
list1 = [hij, klm, opq]
list1 = [hij, klm]
list1 = []

注意:遍历删除时,一定要使用迭代器删除。代码如下:

public static void main(String[] args) throws InterruptedException {
    
    ArrayList<String> list1 = new ArrayList<>();
    list1.add("abc");
    list1.add("def");
    list1.add("hij");
    list1.add("klm");
    list1.add("opq");
    list1.add("rst");
    System.out.println("list1 = " + list1);
    //遍历删除时使用迭代器
    Iterator iterator = list1.iterator();
    while (iterator.hasNext()){
    
        if ("klm".equals(iterator.next())){
    
            iterator.remove();
        }
    }
    System.out.println("list1 = " + list1);
}

输出如下:

list1 = [abc, def, hij, klm, opq, rst]
list1 = [abc, def, hij, opq, rst]

其他方法

public static void main(String[] args) throws InterruptedException {
    
    ArrayList<String> list1 = new ArrayList<>();
    list1.add("abc");
    list1.add("def");
    list1.add("hij");
    list1.add("klm");
    //是否包含某元素
    System.out.println("是否包含abc " + list1.contains("abc"));
    //某元素的index
    System.out.println("abc的位置 " + list1.indexOf("abc"));
    //获得某个index的元素值
    System.out.println("1位置元素值是 " + list1.get(1));
}

输出如下:

是否包含abc true
abc的位置 0
1位置元素值是 def

ArrayList其他

扩容机制
空ArrayList对象是DEFAULTCAPACITY_EMPTY_ELEMENTDATA,当第一个元素被添加时,数组容量会变成DEFAULT_CAPACITY。

    /**
     * Default initial capacity.默认初始容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     * 被用于空实例的共享空数组实例
     */
    private static final Object[] EMPTY_ELEMENTDATA = {
    };

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     * 被用于默认大小的空实例的共享数组实例。
     * 其与EMPTY_ELEMENTDATA的区别是,当我们添加第一个元素时,知道数组该扩充多少。
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
    };

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     * 存放ArrayList元素的数组缓冲区。ArrayList的容量就是这个数组缓冲区的长度。 
     * 添加第一个元素时,任何带有 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * 的空 ArrayList 都将扩展为 DEFAULT_CAPACITY。
     */
    // non-private to simplify nested class access
    // 非private是为了方便嵌套类的访问
    transient Object[] elementData; 
    /**
     * Constructs an empty list with an initial capacity of ten.
     * 构造空集合时初始容量是10
     */
    public ArrayList() {
    
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

注意容量(capacity )和size不是一个值的。size是具体存了几个元素,而容量是可以存多少元素。
扩容函数如下:

    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    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);
    }
    private static int hugeCapacity(int minCapacity) {
    
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

先将容量扩容1.5倍,与保证放下所有元素的最小容量比较,如果够,就扩容1.5,否则判断是否达到集合存储最大值,如果到达了按照hugeCapacity方法返回值扩充。

扩容使用Arrays.copyOf方法,底层是System.arraycopy方法,它是一个JVM提供的高效数组拷贝实现。

    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

快速失败机制
ArrayList中通过modCoun来实现"Fail-Fast"的错误检测机制,当多个线程对同一集合的内容进行操作时,可能就会产生异常。
迭代器初始化是,会将modCoun赋值给expectedModCount,当进行一些修改结构的操作时,比如remove相关的,扩容,清空等操作时,modCount++,而迭代过程中判断expectedModCount和modCount是否一致,如果不相等,意味着有其他线程修改了结构,此时就会抛出ConcurrentModificationException异常。
比如清除方法中:

    public void clear() {
    
        modCount++;
        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;
        size = 0;
    }

而Itr迭代器中有方法来判断值是否相等,是否抛异常:

        final void checkForComodification() {
    
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43554422/article/details/119411090

智能推荐

dubbo端口冲突解决办法_dubbo 多个服务抢占端口-程序员宅基地

文章浏览阅读2.8k次。在一台机子上部署多个dubbo服务,将各服务的dubbo端口号设为-1,可以确保无端口冲突。_dubbo 多个服务抢占端口

【CISSP备考】第七章-安全运营_cissp sox法案-程序员宅基地

文章浏览阅读2.1k次。第六章密码学和对称秘钥算法:密码可为已存储(静止中)、通过网络传送(传输中)和存在于内存中(使用中)的敏感信息提供保密性、完整性、身份验证和不可否认性保护。凯撒密码:将相关字母顺移密码学的目标:保密性、完整性、身份验证和不可否认性1、保密性:保密性是确保数据在静止、传输和使用等三种不同状态下始终保持私密对称加密系统、非对称加密系统2、完整性完整性确保数据没有被人未经授权更改、消息完整性使用加密的消息摘要实现3、身份验证身份验证用于验证系统用户所声称的身份,是密码系_cissp sox法案

微信小程序开发:实现地图导航功能_微信小程序地图导航功能实现-程序员宅基地

文章浏览阅读4.8k次,点赞2次,收藏25次。其中,id用于调用地图组件,latitude和longitude表示地图的中心点坐标,markers表示地图中的标记点,covers表示地图中的覆盖物,polyline表示地图中的折线图,show-location表示是否显示当前定位点,bindregionchange表示移动地图时触发的事件。其中,id表示标记点的唯一标识,latitude和longitude表示标记点的坐标,title表示标记点的名称,iconPath表示标记点的图标路径,width和height表示标记点的宽度和高度。_微信小程序地图导航功能实现

Invalid initial heap size: -Xms-程序员宅基地

文章浏览阅读4.9k次。-Xxs512m注意 Xxs 和 512m中间无空格就行了。_invalid initial heap size: -xms4g

pycharm不识别turtle的解决方法_pycharm turtleshape-程序员宅基地

文章浏览阅读4.7k次,点赞4次,收藏7次。原因pycharm和turtle库有冲突,不能自己识别出turtle下的方法:解决方案找到turtle.py, 对turtle库的源码进行如下修改: 注释掉原来的_ all_,新增如下:# __all__ = (_tg_classes + _tg_screen_functions + _tg_turtle_functions +# _tg_utiliti..._pycharm turtleshape

高斯采样的仿真(python实现)_python 从高斯分布中采样-程序员宅基地

文章浏览阅读1.9k次,点赞2次,收藏11次。英文版的原文Introduction to Gaussian Processes - Part I中文翻译版的原文图文详解高斯过程(一)——含代码_python 从高斯分布中采样

随便推点

SVN不完全指南(使用)_svn authz文件在哪-程序员宅基地

文章浏览阅读238次。目录一 、SVN三大指令(检提更) 二、忽略功能 三、版本回退 四、版本冲突 五、配置多仓库与权限控制 六、SVN服务的配置与管理 七、模拟真实的开发环境一 、SVN三大指令(检提更)检出(Checkout)操作 首先在你的项目目录鼠标右键TortoiseSVN版本库浏览器输出SVN服务器地址: svn://SVN服务器地址 Shop项目(仓库) 注: 因为.svn是隐藏_svn authz文件在哪

SpringBoot 不同环境读取不同的配置信息文件_根据不同环境获取不同的配置信息-程序员宅基地

文章浏览阅读1.3w次。在实际开发中,本地开发、测试服务、正式服务的配置信息有的地方是不一样的;比如本地测试log级别可能是debug,而正式环境下则为info;再比如数据库的配置,正式环境下和测试环境下是不一样的。以前我们通过手动更改这些配置来完成测试到正式的转移,但这样做还是有一定的风险,如果手动配置错误,则会导致很多错误。Springboot给我们提供了一种方式,能够自动的切换正式环境配置及测试环境配置,下面就用一个_根据不同环境获取不同的配置信息

国货之光,处女座的福音!最详细华强北洛达1562M悦虎版二代蓝牙耳机评测_1562m支持蓝牙-程序员宅基地

文章浏览阅读9.4k次。2016年,随着苹果发布初代AirPods,原来一直不愠不火的蓝牙耳机市场一时大热,“真无线蓝牙耳机”(简称TWS,True Wireless Stereo)开始走进人们的视野。随着各大手机厂商(奸商)取消手机上的3.5mm耳机插口,真无线蓝牙耳机加速普及,直至今天变成人们手中不可或缺的电子产品。然而,面对苹果动辄上千的高昂售价,AirPods仍然让许多人望尘莫及,华强北的蓝牙耳机此时应运而生。华强北的蓝牙耳机走到今天已经是第五个年头了,从一开始的邯郸学步、东施效颦到今天功能、工艺日趋完美甚至续航超越原版,_1562m支持蓝牙

数据库MySQL学习笔记高级篇(周阳)_mysql进阶周阳-程序员宅基地

文章浏览阅读1.6k次,点赞3次,收藏28次。数据库MySQL学习笔记高级篇1. mysql的架构介绍mysql简介高级MysqlmysqlLinux版的安装mysql配置文件mysql逻辑架构介绍mysql存储引擎2. 索引优化分析性能下降SQL慢常见通用的Join查询索引简介性能分析索引优化3. 查询截取分析查询优化1. mysql的架构介绍mysql简介高级Mysql完整的mysql优化需要很深的功底,大公司甚至有专门的DBA写上述mysql内核sql优化工程师mysql服务器的优化各种参数常量设定查询语句优化主从复制软_mysql进阶周阳

基于SpringBoot+Vue+uniapp微信小程序的消防隐患在线举报系统的详细设计和实现-程序员宅基地

文章浏览阅读775次,点赞26次,收藏20次。博主介绍:全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战精彩专栏 推荐订阅2023-2024年最值得选的微信小程序毕业设计选题大全:100个热门选题推荐2023-2024年最值得选的Java毕业设计选题大全:500个热门选题推荐Java精品实战案例《500套》微信小程序项目精品案例《500套》文末获取源码+数据库。

GC日志分析_已追加形式gc日志-程序员宅基地

文章浏览阅读2.1w次,点赞17次,收藏57次。通过 -XX:+PrintGCDetails 启用日志GC (minor )日志Full GC 日志_已追加形式gc日志

推荐文章

热门文章

相关标签