Java中的数组和集合

一、List和Map

Java中的数组和集合

1、特点

(1)传统的数组结构存储数据会在内存中开辟连续得空间,结合下标从而使得可以快速访问数据,但是删除和添加数据就很浪费资源

Java中的数组和集合
(2)链表不需要开辟连续空间,使用指针来指向数据,因此删除和添加操作比较快,但是查询数据需要遍历全部得元素
Java中的数组和集合
(3)而哈希表[散列表]结合两者得长处,合二为一。使得哈希表比较牛掰(初始容量,数组长度默认为16,分为单指针和双指针,双指针每个元素指向前面元素同时指向后面元素)
Java中的数组和集合

(1)、List

1、可以允许重复的对象。
2、可以插入多个null元素。
3、是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序。
4、常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList 最为流行,它提供了使用索引的随意访问,而 LinkedList 则对于经常需要从 List 中添加或删除元素的场合更为合适。

(2)、Map

1、不是collection的子接口或者实现类。Map是一个接口。
2、Map的每个 Entry 都持有两个对象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。
3、TreeMap 也通过 Comparator 或者 Comparable 维护了一个排序顺序。
4、Map 里你可以拥有随意个 null 值但最多只能有一个 null 键。
5、Map 接口最流行的几个实现类是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用)。

(3)、区别

1、list是存储单列数据的集合,map是存储双列数据的集合;
2、list中存储的数据是有序的,map中存储的数据是无序的;
3、list允许重复,map的键不能重复,值可以重复。

(4)、Array和ArrayList

Array(数组)是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的。
Array获取数据的时间复杂度是O(1),但是要删除数据却是开销很大,因为这需要重排数组中的所有数据。
List
List—是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式,它继承Collection。
1、ArrayList底层采用数组实现,当使用不带参数的构造方法生成ArrayList对象时,实际上会在底层生成一个长度为10的Object类型的数组。
2、如果增加的元素个数超过10个,那么ArrayList底层会生成一个新的数组,长度为原数组的1.5倍+1,然后将原数组的内容复制到新数组中,并且后续增加的内容都会放到新的数组当中,当新的数组无法容纳增加的元素时,重读该过程。
3、对于ArrayList元素的删除操作,需要将被删除元素的后续元素向前移动,代价比较大。
4、集合当中只能放置对象的引用,无法放置原生数据类型,我们必须使用原生数据的包装类才能加入到集合当中。
5、集合当中都是Object类型,因此取出来的也是Object类型,那么必须要使用强制类型转化将其转换成真正的类型(放置进去的类型)。

二、List

1、Arraylist和Vector的区别

(1)、都实现了List接口( List接口继承了Collection接口)都是有序集合List集合规范制定(数据允许重复,可有通过索引取出数据)

(2)、ArrayList和Vector都是基于数组,因此大致代码相似。区别在于 Vector在Jdk1.0就有的古老集合, 因此包含大量方法名很长的方法。 Jdk1.2开始引入集合框架引入了List接口 Vector实现了List接口因此增加了一些List接口中的方法

(3)、总体来讲ArrayList可以完全取代Vector,除非有一些老古董强制要求Vector。Vectory是线程安全的因此性能较差。ArrayList是非线程安全所以接口性能较好。即使在多线程中也应该用ArrayList,因为 可以通过Collections吧ArrayList和LInkedList转换成一个线程安全的集合
例子: List ls = Collections.synchronizedList(new ArrayList<>());

(1)、ArrayList Vector ==>> 数组方式存储数据
数组元素的数据 > 实际存储的数据以及增加和插入元素
按序号索引元素
插入元素 ==>>数组移动等内存操作
索引数据快、插入数据慢
(2)、Vector ==>> synchronized方法(线程安全)
性能上较ArrayList差
(3)、LinkedList ==>> 双向链表实现存储
序号索引数据需要向前或向后遍历
插入数据时只需要记录本项的前后项即可
所以插入速度较快
线程不安全

(1)、ArrayList

特点:
1、ArrayList 内部是通过动态数组实现的,它允许对元素进行快速随机访问;
2、当数组大小不满足时需要扩容,需要将已有数组移动到新的内存空间;
3、当从 ArrayList 的中间位置插入或者删除元素时,需要对数组进行复制、移动代价比较高;
4、线程不安全。

初始容量:10初始容量:10
扩容容量:(原始容量 x 3 ) / 2 + 1。
适用场景:ArrayList 适合单线程,或多线程环境,但 List 只会被单个线程操作;随机查找和遍历,不适合插入和删除。

特点:
1、LinkedList 是基于双向链表存储数据的,很适合数据的动态插入和删除;
2、可根据索引值获取(get(int index)))或删除(remove(int index))节点(实现原理:通过计数索引值实现,当 index > 链表长度的1/2,从链表尾部开始遍历;反之,从链表头部开始遍历;
3、可作为队列和栈使用
4、线程不安全。
5、相对于ArrayList,LinkedList插入是更快的。因为LinkedList不像ArrayList一样,不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重新装入一个新的数组,这是ArrayList最坏的一种情况,时间复杂度是O(n),而LinkedList中插入或删除的时间复杂度仅为O(1)。ArrayList在插入数据时还需要更新索引(除了插入数组的尾部)。
6、类似于插入数据,删除数据时,LinkedList也优于ArrayList。
7、LinkedList需要更多的内存,因为ArrayList的每个索引的位置是实际的数据,而LinkedList中的每个节点中存储的是实际的数据和前后节点的位置。

适用场景:适合单线程中,顺序读取,不适合随机读取和随机删除。

(3)、Vecor

特点:
1、其特点大致与 ArrayList 一样。
2、线程安全(因为内部方法都是通过 synchronized 关键字同步的)。

初始容量:10初始容量:10
扩容容量:若扩容系数 > 0,则将容量的值增加”扩容系数”;否则,将容量大小增加一倍。
适用场景:能不用就别用。

顺序插入速度ArrayList会比较快,因为ArrayList是基于数组实现的,数组是事先new好的,只要往指定位置 塞一个数据就好了
LinkedList则不同,每次顺序插入的时候LinkedList将new一个对象出来,如果对象比较大,那么new的时间 势必会长一点,再加上一些引用赋值的操作,所以顺序插入LinkedList必然慢于ArrayList
ArrayList的遍历效率会比LinkedList的遍历效率高一些

LinkedList做插入、删除的时候,慢在寻址,快在只需要改变前后Node的引用地址

ArrayList做插入、删除的时候,慢在数组元素的批量copy,快在寻址

如果确定插入、删除的元素是在前半段,那么就使用LinkedList

如果确定插入、删除的元素在比较靠后的位置,那么可以考虑使用ArrayList

如果不能确定插入、删除是在哪儿呢?建议使用LinkedList,

一来LinkedList整体插入、删除的执行效率比较稳定,没有ArrayList这种越往后越快的情况

二来插入元素的时候,弄得不好ArrayList就要进行一次扩容,而ArrayList底层数组扩容是一个既消 耗时间又消耗空间的操作

三、Map

Hash也称散列。基本原理就是把任意长度的输入,通过Hash算法变成固定长度得输出,这个映射得规则对应的就是Hash算法,而原始数据映射后得二进制串就是Hash值

entry—-key—-hash—-index哈希值就是把各种类型的key算成统一的下标(.hashcode())

Java中的数组和集合
Hash&#x7279;&#x70B9;
    1&#x3001;&#x4ECE;Hash&#x503C;&#x4E0D;&#x53EF;&#x53CD;&#x5411;&#x63A8;&#x5BFC;&#x51FA;&#x539F;&#x59CB;&#x6570;&#x636E;
    2&#x3001;&#x8F93;&#x5165;&#x6570;&#x636E;&#x7684;&#x5FAE;&#x5C0F;&#x53D8;&#x5316;&#x4E5F;&#x4F1A;&#x5F97;&#x5230;&#x5B8C;&#x5168;&#x4E0D;&#x540C;&#x7684;hash&#x503C;&#xFF0C;&#x76F8;&#x540C;&#x7684;&#x6570;&#x636E;&#x7684;&#x9053;&#x76F8;&#x540C;&#x7684;hash&#x503C;
    3&#x3001;&#x54C8;&#x5E0C;&#x7B97;&#x6CD5;&#x6267;&#x884C;&#x9AD8;&#x6548;&#xFF0C;&#x957F;&#x6587;&#x672C;&#x4E5F;&#x80FD;&#x5FEB;&#x901F;&#x8BA1;&#x7B97;&#x51FA;&#x54C8;&#x5E0C;
    4&#x3001;Hash&#x7B97;&#x6CD5;&#x51B2;&#x7A81;&#x6982;&#x7387;&#x8F83;&#x5C0F;

Hash&#x8868;&#x5728;jdk1.7&#x4E2D;&#x4F7F;&#x7528;&#x6570;&#x7EC4;+&#x94FE;&#x8868; jdk1.8&#x4E2D;&#x52A0;&#x5165;&#x4E86;&#x7EA2;&#x9ED1;&#x6811;
&#x7531;&#x4E8E;Hash&#x7684;&#x539F;&#x7406;&#x662F;&#x5C06; &#x8F93;&#x5165;&#x7A7A;&#x95F4;&#x7684;&#x503C; &#x6620;&#x5C04;&#x6210; hash&#x7A7A;&#x95F4;&#x5185;&#xFF0C;&#x800C;hash&#x503C;&#x7A7A;&#x95F4;&#x8FDC;&#x5C0F;&#x4E8E;&#x8F93;&#x5165;&#x7684;&#x7A7A;&#x95F4;&#x3002;
&#x6839;&#x636E;&#x62BD;&#x5C49;&#x539F;&#x7406;&#xFF0C;&#x4E00;&#x5B9A;&#x4F1A;&#x5B58;&#x5728;&#x4E0D;&#x540C;&#x7684;&#x8F93;&#x5165;&#x88AB;&#x6620;&#x5C04;&#x6210;&#x76F8;&#x540C;&#x7684;&#x8F93;&#x51FA;&#x3002;

&#x62BD;&#x5C49;&#x539F;&#x7406;&#xFF1A;9&#x4E2A;&#x62BD;&#x5C49;&#x653E;10&#x4E2A;&#x82F9;&#x679C;&#xFF0C;&#x600E;&#x4E48;&#x653E;&#x90FD;&#x4F1A;&#x6709;&#x4E00;&#x4E2A;&#x62BD;&#x5C49;&#x91CC;&#x6709;2&#x4E2A;&#x53CA;&#x4EE5;&#x4E0A;&#x7684;&#x82F9;&#x679C;

(5)HashMap的继承体系

Java中的数组和集合

1、HashMap与HashTable简介

类似于ArrayList和LinkedList的区别, HashTable是JDK1.0 就存在的老东西,因此 HashTable是一个继承Dictionary 的古老集合。JDk1.2引入了集合框架的Map接口,HashTable也实现了Map接口,因此HashTable也增加了一些Map的方法

2、HashMap与HashTable区别

(1)、HashMap允许使用null作为Key或者Value,HashTable不允许
(2)、HashMap是线程不安全的因此性能较好,而HashTable是线程安全的因此性能较差

3、场景

多线程环境下也是用HashMap,Collections可以把HashMap转换成线程安全的集合.

例: Map map = Collections.synchronizedList(new HashMap())

4、底层一些常量与属性和构造方法

&#x5E38;&#x91CF;&#xFF1A;
    //&#x7F3A;&#x7701;&#x5927;&#x5C0F;
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    //&#x6570;&#x7EC4;&#x7684;&#x6700;&#x5927;&#x957F;&#x5EA6;
    static final int MAXIMUM_CAPACITY = 1 << 30;

    //&#x7F3A;&#x7701;&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;&#x5927;&#x5C0F;
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    //&#x6811;&#x5316;&#x9608;&#x503C;&#xFF08;&#x94FE;&#x8868;&#x957F;&#x5EA6;&#x8D85;&#x8FC7;8&#x4E4B;&#x540E;&#x5E76;&#x4E14;&#x6570;&#x7EC4;&#x957F;&#x5EA6;&#x5927;&#x4E8E;64&#x5C31;&#x4F1A;&#x5347;&#x7EA7;&#x6210;&#x4E00;&#x4E2A;&#x6811;&#x4E86;&#xFF09;
    static final int TREEIFY_THRESHOLD = 8;

    //&#x6811;&#x964D;&#x7EA7;&#x6210;&#x4E3A;&#x94FE;&#x8868;&#x7684;&#x9608;&#x503C;&#xFF08;&#x5220;&#x9664;&#x6811;&#x4E2D;&#x5143;&#x7D20;&#xFF0C;&#x5143;&#x7D20;=6&#x964D;&#x7EA7;&#x4E3A;&#x94FE;&#x8868;&#xFF09;
    static final int UNTREEIFY_THRESHOLD = 6;

    //&#x6570;&#x7EC4;&#x957F;&#x5EA6;&#x5927;&#x4E8E;64&#xFF08;&#x5E76;&#x4E14;&#x67D0;&#x4E2A;&#x94FE;&#x8868;&#x957F;&#x5EA6;>8&#xFF09;&#x5347;&#x7EA7;&#x4E3A;&#x7EA2;&#x9ED1;&#x6811;
    static final int MIN_TREEIFY_CAPACITY = 64;

&#x5C5E;&#x6027;&#xFF1A;
    //Hash&#x8868;&#xFF0C;put&#x65F6;&#x521D;&#x59CB;&#x5316;
    transient Node<k,v>[] table;

    //
    transient Set<map.entry<k,v>> entrySet;

    //&#x5F53;&#x524D;Hash&#x8868;&#x4E2D;&#x5143;&#x7D20;&#x4E2A;&#x6570;
    transient int size;

    //&#x5F53;&#x524D;Hash&#x8868;&#x7ED3;&#x6784;&#x4FEE;&#x6539;&#x6B21;&#x6570;&#xFF08;&#x63D2;&#x5165;&#x5143;&#x7D20;&#x6216;&#x5220;&#x9664;&#x5143;&#x7D20;&#xFF0C;&#x66FF;&#x6362;&#x4E0D;&#x4F1A;&#x8BA1;&#x6570;&#xFF09;
    transient int modCount;

    //&#x6269;&#x5BB9;&#x9608;&#x503C;&#xFF08;Hash&#x8868;&#x4E2D;&#x5143;&#x7D20;&#x8D85;&#x8FC7;&#x9608;&#x503C;&#x65F6;&#x89E6;&#x53D1;&#x6269;&#x5BB9;&#xFF0C;&#x8D85;&#x8FC7;&#x9608;&#x503C;&#x4E0D;&#x6269;&#x5BB9;&#x5F71;&#x54CD;&#x67E5;&#x627E;&#x6027;&#x80FD;&#x3002;&#x94FE;&#x5316;&#x4E25;&#x91CD;&#xFF09;
    int threshold;

    //&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;&#xFF08;&#x8BA1;&#x7B97;threshold = capacity&#x6570;&#x7EC4;&#x957F;&#x5EA6;  *loadFactor&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;&#xFF09;
    final float loadFactor;

&#x6784;&#x9020;&#x65B9;&#x6CD5;&#xFF1A;
    //
    public HashMap(int initialCapacity, float loadFactor) {
        //&#x505A;&#x4E86;&#x903B;&#x8F91;&#x6821;&#x9A8C;
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                               initialCapacity);
        //&#x4F20;&#x5165;&#x6570;&#x7EC4;&#x957F;&#x5EA6;&#x8D85;&#x8FC7;&#x6700;&#x5927;&#x957F;&#x5EA6;&#x5C31;&#x8BBE;&#x7F6E;&#x4E3A;&#x6700;&#x5927;&#x957F;&#x5EA6;
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        //&#x8D1F;&#x8F7D;&#x56E0;&#x5B50;<=0。。。。||不是数 if (loadfactor <="0" || float.isnan(loadfactor)) throw new illegalargumentexception("illegal load factor: " + loadfactor); 赋值负载因子 this.loadfactor="loadFactor;" 赋值扩容阈值 位移计算只能是2的次方数导致table的长度只能是2的次方 传过来init。。为7计算为8,9计算为16 this.threshold="tableSizeFor(initialCapacity);" } 设置默认负载因子 public hashmap() { all other fields defaulted code></=0。。。。||不是数></map.entry<k,v></k,v>

5、put源码分析

put&#x65B9;&#x6CD5;&#x65F6;&#x4F1A;&#x9ED8;&#x8BA4;&#xFF08;new entry&#xFF08;key&#xFF0C;value&#xFF0C;null=&#x6307;&#x9488;next&#xFF09;&#xFF09;

public V put(K key, V value) {
    //table&#x7684;length&#x4E0D;&#x662F;&#x7279;&#x53D8;&#x957F;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#xFF0C;&#x8BA9;&#x8BA9;key&#x7684;hash&#x503C;&#x9AD8;&#x4E8E;16&#x4F4D;&#x4E5F;&#x53C2;&#x4E0E;&#x8DEF;&#x7531;&#x8FD0;&#x7B97;
    return putVal(hash(key), key, value, false, true);
}

//&#x5B9E;&#x9645;&#x7528;put&#x5411;&#x6563;&#x5217;&#x8868;&#x63D2;&#x5165;&#x6570;&#x636E;
/**
     * Implements Map.put and related methods
     *
     * @param hash hash for key
     * @param key the key
     * @param value the value to put
     * @param onlyIfAbsent&#x6563;&#x5217;&#x8868;&#x5B58;&#x5728;&#x6B32;&#x63D2;&#x5165;&#x7684;key&#x5C31;&#x4E0D;&#x63D2;&#x4E86;&#xFF08;&#x6709;&#x5C31;&#x66FF;&#x6362;&#xFF09;
     * @param evict
     * @return previous value, or null if none
     */
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {

    //tab&#xFF1A;&#x5F15;&#x7528;&#x5F53;&#x524D;HashMap&#x7684;&#x6563;&#x5217;&#x8868;
    //p&#xFF1A;&#x8868;&#x793A;&#x5F53;&#x524D;&#x6563;&#x5217;&#x8868;&#x7684;&#x5143;&#x7D20;
    //n&#xFF1A;&#x8868;&#x793A;&#x6563;&#x5217;&#x8868;&#x6570;&#x7EC4;&#x7684;&#x957F;&#x5EA6;
    //i&#xFF1A;&#x8868;&#x793A;&#x8DEF;&#x7531;&#x5BFB;&#x5740; &#x7ED3;&#x679C;

    Node<k,v>[] tab; Node<k,v> p; int n, i;

    //&#x7B2C;&#x4E00;&#x6B21;&#x63D2;&#x5165;&#x6570;&#x636E;&#x65F6;&#x624D;&#x4F1A;&#x521D;&#x59CB;&#x5316;&#xFF0C;&#x53EA;&#x662F;new&#x51FA;&#x6765;&#x5E76;&#x4E0D;&#x4F1A;&#x521D;&#x59CB;&#x5316;&#xFF08;&#x597D;&#x591A;new&#x51FA;&#x6765;&#x4F46;&#x5E76;&#x4E0D;&#x7528;&#xFF09;
        //&#x5EF6;&#x8FDF;&#x521D;&#x59CB;&#x5316;&#x903B;&#x8F91;
    if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;

    //&#x5BFB;&#x5740;&#x627E;&#x6876;&#x4F4D;&#xFF0C;&#x521A;&#x597D;&#x4E3A;null&#xFF0C;&#x8FD9;&#x65F6;&#x76F4;&#x63A5;&#x5C06;&#x5F53;&#x524D;key-value&#x8F6C;&#x6210;node&#x585E;&#x8FDB;&#x53BB;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<k,v> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<k,v>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
</k,v></k,v></k,v></k,v>

总的来说向Vector和HashTable这种JDK1.0产物尽量不使用,除非某些api强制使用~~~果然老东西得退休~

Java中的数组和集合

Original: https://www.cnblogs.com/pkkyh/p/14868124.html
Author: 迷途者寻影而行
Title: Java中的数组和集合

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/575743/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 正则表达式=Regex=regular expression

    正则表达式=Regex=regular expression 反向引用*2 \index索引引用 \b(\w+)\b\s+\1\b \k \b(? 数量符/限定符62 贪婪Gree…

    数据库 2023年6月15日
    069
  • SNMP基础简介

    近来,公司产品开发涉及到SNMP方面的知识, 在此作一些总结,或许对您现在或者将来有用。 在目前越来越复杂的网络环境中,整个环境有各种各样的网络设备,为了能更好的对这些设备进行管理…

    数据库 2023年6月11日
    089
  • 了解HTML/CSS/JS/JQuery/ajax等前端知识

    什么是HTML 超文本标记语言 浏览器通过识别相应的标签来加载页面 通过HTTP协议传输,不是编程语言 HTML常用标签 title script style link meta …

    数据库 2023年6月16日
    0137
  • MySQL select语句中where条件的提取过程

    select语句中where条件的提取过程 孔个个依然,在整理where条件提取过程时,发现中文互联网上关于这一块的知识要么是存在错误自相矛盾的,要么是版本过老,遂自己整理了一版。…

    数据库 2023年6月16日
    093
  • 汇编实验二设置栈顶

    实验笔记二:ss设置栈顶 mov ax,2000 mov ss,ax mov sp,0010 mov ax,2000 mov ss,ax mov sp,0010 执行后,内存地址会…

    数据库 2023年6月11日
    079
  • web 前端 基础HTML知识点

    B/S(Browser/Server):浏览器实现 优点: 规范、使用方便、本身实现成本低 容易升级、便于维护 缺点: 没有网络,无法使用 保存数据量有限,和服务器交互频率高、耗费…

    数据库 2023年6月16日
    076
  • 解决.net6 Docker容器 DateTime.Now 获取时间相差8小时问题(转载)

    .net6项目中使用DateTime.Now获取到的时间比本地时间要差8小时,但是docker容器中,使用date获取的时间是正确的,网上提供了很多种方法,主要有以下三种方法,其中…

    数据库 2023年6月9日
    0147
  • 1_requests基础用法

    requests 模块的基本使用 什么是requests 模块? Python 中封装好的一个基于网络请求的模块 requests 模块的作用? 用来模拟浏览器发请求 reques…

    数据库 2023年6月11日
    079
  • Linux–>shell

    shell是什么 Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序。 用户可以用Shell来启动,挂起,停止,编写一些程序。 S…

    数据库 2023年6月14日
    0109
  • SpringBoot下配置文件密码加密

    一、导入配置文件 csharp;gutter:true; com.github.ulisesbocchio jasypt-spring-boot-starter 3.0.4<…

    数据库 2023年6月14日
    080
  • 设计模式之抽象工厂

    一、抽象工厂:不管是简单工厂还是工厂方法,他们创建的都是同一类对象,有时候需要一组一组的创建对象,如果需要创建一组对象,抽象工厂是最好的方式,而抽象工厂的目的旨在创建一组包含多种不…

    数据库 2023年6月14日
    076
  • MVCC – Read View的可见性判断理解

    读了 @SnailMann大佬【MySQL笔记】正确的理解MySQL的MVCC及实现原理 收益颇丰,非常感谢! 但对其中如何判断事务是否可见性还是不太理解,于是作了本文,在原博客基…

    数据库 2023年5月24日
    092
  • 记一次有意思的 SQL 实现 → 分组后取每组的第一条记录

    开心一刻 今天,我的朋友怒气冲冲地向我走来。 [En] Today, my friend came up to me angrily. 朋友:我和一个女朋友聊了三个月了。我昨天偷看…

    数据库 2023年5月24日
    0135
  • 中文技术文档写作规范

    使用 markdown 格式书写文档 只使用一二三级标题,三级标题下面的并列性内容使用列表展示 二级标题前使用行分隔符表示分隔 段落之间使用一个空行隔开 一句话或者以逗号分隔的句子…

    数据库 2023年6月6日
    083
  • MySQL行构造器

    子查询返回多列的办法 主要用途,项目中初版使用子查询返回一列用来限制主表,项目新版本中,表关联建改为多列时建议使用 Original: https://www.cnblogs.co…

    数据库 2023年6月9日
    079
  • index_merge引发的死锁排查

    前几天排查了一个死锁问题,最开始百思不得其解,因为发生死锁的两个事务是单语句事务,语句类型相同(where属性列相同,仅值不同),而且语句都走了相同的索引,但最终确实发生了死锁。通…

    数据库 2023年6月9日
    0115
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球