简单的聊一下JAVA集合(SXL),有什么不对的欢迎指正!

一、ArrayList

数组集合应用

        // ArraysList 增删慢 查询快
        // 根据源码 无参构造方法创建出来的是长度为0的数组{}
        List<Integer> list = new ArrayList<>();
        // 此时add方法进行源码扩容
        list.add(100);
        System.out.println(list.get(0));

add()方法扩容源码

    public boolean add(E e) {
        // 不需要关注
        modCount++;
        // e对象 elementData集合数组元素 size当前数组长度
        add(e, elementData, size);
        // 不管成功失败 均返回true
        return true;
    }
    
    private void add(E e, Object[] elementData, int s) {
        // 满足条件 进入扩容算法 不然就进行正常赋值操作
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }
    
    private Object[] grow() {
        // 至少需要加一个长度 
        return grow(size + 1);
    }
    
    private Object[] grow(int minCapacity) {
        return elementData = Arrays.copyOf(elementData,
                                           newCapacity(minCapacity));
    }

    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        // 新长度加上旧长度的0.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity <= 0) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                // DEFAULT_CAPACITY 默认长度10
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            // 超出最大二进制,符号会改变,会变为负数
            if (minCapacity < 0) // overflow
                throw new OutOfMemoryError();
            return minCapacity;
        }
        
        // MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
        return (newCapacity - MAX_ARRAY_SIZE <= 0)
            ? newCapacity
            : hugeCapacity(minCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE)
            ? Integer.MAX_VALUE
            : MAX_ARRAY_SIZE;
    }

二、LinkedList

        // LinkedList: 使用双向链表结构,增删快,查找慢
        // (这种结构和ArrayList的数组结构正好是互补状态)
        LinkedList<Integer> ll = new LinkedList<>();

        // 模拟栈结构
        // 压栈
        ll.push(100);
        ll.push(200);
        // 弹栈
        Integer i = ll.pop();
        // 200
        System.out.println(i);
        // 1
        System.out.println(ll.size());

        // 下面注释参考 不建议使用
        // 添加集合中第一个元素
        // ll.addFirst(100);
        // ll.addFirst(200);
        // 移除集合中第一个元素
        // Integer removeData = ll.removeFirst();
        // 200
        // System.out.println(removeData);
        // 1
        // System.out.println(ll.size());

三、Vector

用法和ArrayList基本一致,是线程安全的。

        // 10 初始化长度 20 扩容增量 此处是相较于ArrayList不同之处
        List<Integer> v = new Vector<>(10, 20);
        v.add(100);
        v.add(200);

四、Iterator和ListIterator

        // Iterator 迭代器 作用遍历集合
        // Iterator迭代Collection下List和Set ListIterator迭代List下面的集合
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);

        Iterator<Integer> iterator = list.iterator();

        iterator.next();
        // 必须要有值才能移除即前面调用next()方法,当然没值也会报错
        iterator.remove();;
        // 4
        System.out.println(list.size());

        // 判断迭代器下个是否有值
        while(iterator.hasNext()) {
            // 迭代器往下走,并取值
            Integer i = iterator.next();
            // 输出 2 3 4 5
            System.out.println(i);
        }

        // 用法和iterator差不多
        ListIterator<Integer> listIterator = list.listIterator();
        // 获取向上走的值
        listIterator.hasPrevious();
        // 添加
        listIterator.add(10);
        // 设置
        listIterator.next();
        listIterator.set(200);
        listIterator.previous();
        // 5
        System.out.println(list.size());
        while(listIterator.hasNext()) {
            // 输出 200 3 4 5
            System.out.println(listIterator.next());
        }

五、Set

Set集合是没有重复的元素,包括null只会存在一个

5.1 HashSet

        // HashSet是散列存放的数据结构(哈希表)
        // 本质是 map = new HashMap<>()
        // 由于已经存在双值存储的哈希表 所以这边重复利用了形成现在的单值存储的哈希表
        Set<String> set = new HashSet<>();
        // map.put(e, PRESENT)
        set.add("人有悲欢离合");
        set.add("月有阴晴圆缺");
        set.add("但愿人长久");
        set.add("但愿人长久");
        set.add("千里共婵娟");
        set.add("千里共婵娟");
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

5.2 TreeSet

    public static void main(String[] args) {
        // TreeSet 使用二叉树进行存储的 有序(自然顺序)
        Set<Person> set = new TreeSet<>();
        Person p1 = new Person("张三", 13);
        Person p2 = new Person("李四", 14);
        Person p3 = new Person("麻五", 14);
        set.add(p1);
        set.add(p2);
        set.add(p3);
        // 遍历前需制定自己的排序规则, 否则可能报错
        // Person{name='张三', age=13}
        // Person{name='李四', age=14}
        // 比较规则相同的值,不被储存
        for (Person p : set) {
            System.out.println(p);
        }


        // set.add("C");
        // set.add("B");
        // set.add("A");
        // set.add("D");
        // A B C D
        // Iterator<String> iterator = set.iterator();
        // while(iterator.hasNext()) {
        //    System.out.println(iterator.next());
        // }
    }

    static class Person implements Comparable<Person> {

        private String name;

        private int age;

        @Override
        public int compareTo(Person o) {
            // this与0比较
            // 返回this小/0/大
            if (this.age > o.age) {
                return 1;
            } else if (this.age == o.age) {
                return 0;
            }
            return -1;
        }

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

六、Map

Map(Mapping 映射)集合存储的是 键值对 数据,Map的键不可重复。
影响HashMap的实例化性能的是初始容量和负载因子。
HashMap/Hashtable/ConcurrentHashMap TreeMap/LinkedHashMap使用方法基本一致。

HashMap是线程不安全,效率高。HashTable线程安全, 效率低。
ConcurrentHashMap采用分段锁机制,保证线程安全,效率较高。

TreeMap是有序的排。
LinkedHashMap存储有序。

6.1 HashMap

        Map<String, String> map = new HashMap<>();
        // 存值
        map.put("k1", "v1");
        // 取值 v1
        System.out.println(map.get("k1"));
        map.put("k2", "v2");

        // 遍历
        Set<String> set = map.keySet();
        for (String key : set) {
            // k1->v1
            // k2->v2
            System.out.println(key + "->" + map.get(key));
        }

        // 转为Collection集合
        Collection<String> c = map.values();
        for (String s : c) {
            System.out.println(s);
        }

HashMap源码粗解析

    // 构造方法
    public HashMap() {
        // 默认加载因子0.75f
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }

    public V put(K key, V value) {
        // 先计算键的hash值,然后调用putVal
        return putVal(hash(key), key, value, false, true);
    }

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        // n是桶(数组)的长度
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        // table是默认的16个长度的数组赋值给tab
        if ((tab = table) == null || (n = tab.length) == 0)
            // resize扩容算法 n扩容之后的长度
            n = (tab = resize()).length;
        // (n - 1) & hash 是取余后的长度   数组下标没有值直接赋值
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            // key存在新值覆盖老值
            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;
                }
            }
            // 前面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;
    }

总结

在文章的最后作者为大家整理了很多资料!包括java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书等等!
欢迎关注公众号:前程有光,领取!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358

推荐阅读更多精彩内容